Как я могу получить колонку общей цены для модели 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']
Вернуться на верх