Django общая стоимость OrderItems в корзине
Как я могу получить "общую" цену элементов OrderItem в модели cart из этих моделей ниже? Я пытался сделать кое-что в представлениях, но получаю ошибку атрибута, что объект QuerySet' не имеет атрибута 'total'.
views.py
def cart(request):
cart = Cart.objects.filter(order_user=request.user)
order_items = OrderItem.objects.filter(cart__in=cart)
total = 0
for i in order_items:
total = i.quantity * i.item.price + cart.total
cart.update(total=total)
models.py
class OrderItem(models.Model):
cart = models.ForeignKey('Cart', on_delete=CASCADE, null=True)
item = models.ForeignKey(Item, on_delete=CASCADE, null=True)
quantity = models.IntegerField(default=1)
class Item(Visits, models.Model):
title = models.CharField(max_length=150)
price = models.IntegerField(default=1000)
image = models.ImageField(upload_to='pictures', default='static/images/man.png')
description = models.TextField(default="Item")
visits = models.IntegerField(default=0)
class Cart(models.Model):
order_user = models.OneToOneField(User, on_delete=CASCADE)
ordered = models.BooleanField(default=False)
total = models.IntegerField(default=0, help_text="100 = 1EUR")
order_items = models.ManyToManyField(Item, related_name='carts', through=OrderItem )
Проблема возникает в первой строке внутри цикла for, где вы написали:
total = i.quantity * i.item.price + cart.total
Здесь корзина является QuerySet
, поскольку вы использовали filter
, когда извлекали объект cart
из модели Cart в первой строке метода cart. filter
возвращает QuerySet
, а не объект. Вы можете использовать get
для получения объекта cart
, поскольку между моделями Cart и User существует отношение OneToOne. Попробуйте сделать это в первой строке вашего метода cart:
cart = Cart.objects.get(order_user=request.user)
Вы также должны использовать метод save
вместо update
, когда хотите обновить объект. Метод update
принадлежит только QuerySet.
Вы можете получить общее количество через .annotate(…)
[Django-doc] и таким образом вычислить его на стороне базы данных:
from django.db.models import F, Sum
def cart(request):
cart = Cart.objects.annotate(
price=Sum(F('orderitem__item__price') * F('orderitem__quantity'))
).get(
order_user=request.user
)
cart.total = cart.price
cart.save()
# …
Возникающий при этом объект cart
будет иметь дополнительный атрибут .price
, содержащий цену товаров, умноженную на соответствующее количество.
Но это также указывает, почему вы должны не держать поле total
в вашем Cart
: вы можете вычислить его, когда это необходимо.