Как я могу получить колонку общей цены для модели CartItem?
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)
Я пытаюсь получить автоматическую общую цену, которая будет показана на странице оформления заказа. Я хочу добавить колонку 'total_price' в модель CartItem и установить значение по умолчанию 'item.price * qty', но когда я попытался добавить эту строку в класс:
total_price = models.IntegerField(default=item.price)
поскольку значение по умолчанию для qty равно 1, но я получил ошибку AttributeError: 'ForeignKey' object has no attribute 'price'.
Я также попробовал добавить это в класс:
@property
def total_price(self):
item = self.object.get(product=self.item)
return self.item.price
но я не уверен, какая модель будет иметь это свойство? И когда я добавил этот метод, я потерял колонку total_price, которую я установил по умолчанию как 0. Прошу прощения за недостаточное качество решений!
Измените свойство total_price на:
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
И вы можете легко получить общую стоимость позиции заказа.
Если вы хотите получить общую сумму всех цен CartItems, вы можете сделать следующее:
class Cart(models.Model):
@property
def total_amount(self):
self.orders.annotate(total_spent=Sum(
F('item__price') *
F('qty'),
output_field=models.FloatField()
))
Вы находитесь в правильном направлении. Вы можете попробовать аннотацию или агрегацию для получения общей цены. Вот один из подходов:
Для всех элементов корзины, использующих аннотацию с Sum:
Cart.objects.all().annotate(total_spent=Sum(
F('cartitem__item__price') *
F('cartitem__qty'),
output_field=models.FloatField()
))
Для одной корзины можно попробовать вот так с агрегацией:
class Cart(...):
....
@property
def total_price(self):
return self.cartitem_set.aggregate(price=Sum(
F('item__price') *
F('qty'),
output_field=models.FloatField()
)['price']