Reputation: 881
How can I get "total" price of items of OrderItem
in cart model from these models down below? I tried doing something in views but I get attribute error that QuerySet object has no attribute '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 )
Upvotes: 2
Views: 1737
Reputation: 476709
You can get the total through .annotate(…)
[Django-doc] and thus calculate this at the database side:
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()
# …
The cart
object that arises from this will have an extra attribute .price
that contains the price of the items multiplied with the corresponding quantity.
But this also specifies why you should not keep a total
field in your Cart
: you can calculate that when necessary.
Upvotes: 2
Reputation: 86
class OrderItem(DateTimeModel):
order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name="order_items")
product = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField(default=1, blank=True, null=True)
price = models.DecimalField(max_length=100, default=0, max_digits=7, decimal_places=2)
total = models.DecimalField(max_digits=7, decimal_places=2, default=0)
# need to add tax percentage along with it tax may be changed in future so we need to add tax percentage in this
def __str__(self):
return f"{self.id} - {self.order}"
def get_total(self):
return round(float(self.price) * float(self.quantity))
def save(self, *args, **kwargs):
self.total = self.get_total()
super().save(*args, **kwargs)
Upvotes: 0
Reputation: 164
The problem is coming from the first line inside the for loop where you've written:
total = i.quantity * i.item.price + cart.total
Here, the cart is a QuerySet
since you've used filter
when you retrieved the cart
object from Cart model in the first line of cart method. filter
returns QuerySet
, not object. You can use get
to get the cart
object since there is a OneToOne relationship between the Cart and User models. Try this in the first line of your cart method:
cart = Cart.objects.get(order_user=request.user)
You also need to use save
method instead of update
when you want to update an object. update
method belongs to QuerySet only.
Upvotes: 0