class Product(models.Model):
name = models.CharField(max_length=80)
product_image = models.ImageField(upload_to='product/product/images/%Y/%m/%d/', blank=True)
price = models.IntegerField()
class Cart(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
class CartItem(models.Model):
item = models.ForeignKey(Product, null=True, on_delete=models.CASCADE)
qty = models.IntegerField(default=1)
cart = models.ForeignKey(Cart, null=True, on_delete=models.CASCADE)
I'm trying to get an automatic total price that will be shown on check out page. I want to add a 'total_price' column on CartItem model and set the default 'item.price * qty', but when I tried to add this line to the class:
total_price = models.IntegerField(default=item.price)
since default value for qty is 1 but I got AttributeError: 'ForeignKey' object has no attribute 'price' error.
I also tried add this to the class:
@property
def total_price(self):
item = self.object.get(product=self.item)
return self.item.price
but I'm not sure which model will have the property? And when I added this method, I lost total_price column which I set its default as 0. I apologize for the lacking quality of solutions!
CodePudding user response:
You are in right direction. You can try annotation or aggregation to get the total price. Here is one approach:
For all Cart Items using annotation with Sum:
Cart.objects.all().annotate(total_spent=Sum(
F('cartitem__item__price') *
F('cartitem__qty'),
output_field=models.FloatField()
))
For one Cart, you can try like this with aggregation:
class Cart(...):
....
@property
def total_price(self):
return self.cartitem_set.aggregate(price=Sum(
F('item__price') *
F('qty'),
output_field=models.FloatField()
)['price']
CodePudding user response:
Change the total_price property to:
class CartItem(models.Model):
cart = models.ForeignKey(Cart, null=True, on_delete=models.CASCADE,
related_name="orders")
@property
def total_price(self):
return self.qty * self.item.price
And you can easily get the total price of the Order Item.
If you want to get Total amount of all CartItems prices can do like below:
class Cart(models.Model):
@property
def total_amount(self):
self.orders.annotate(total_spent=Sum(
F('item__price') *
F('qty'),
output_field=models.FloatField()
))