Reputation: 57
This is my model for user order
class Order(models.Model):
"""Order Models"""
first_name = models.CharField(
max_length=256,
blank=False,
verbose_name=_('Name'))
total_order_cost = models.DecimalField(
max_digits=10,
decimal_places=2,
default=21,
verbose_name=_('Total Order Cost'))
And my model for ordered items
class OrderItem(models.Model):
""" Ordered Item Model """
order = models.ForeignKey(Order,
verbose_name=_('Order'))
price = models.DecimalField(
max_digits=10,
decimal_places=2,
verbose_name=_('Price'))
quantity = models.PositiveIntegerField(
verbose_name=_('Quantity'))
total_price = models.DecimalField(
max_digits=10,
decimal_places=2,
verbose_name=_('Total Price'))
def get_cost(self):
return self.price * self.quantity
def save(self, *args, **kwargs):
self.total_price = self.get_cost()
super(OrderItem, self).save(*args, **kwargs)
Field total_price gets value from get_cost. How can I make field total_order_cost work the same way? I want it to get value from
def get_total_cost(self):
return sum(item.get_cost() for item in self.items.all())
I can't overwrite method save for total_order_cost, because when I save order object - ordered items don't exist yet. My view:
def make_order(request):
cart = Cart(request)
if request.method == 'POST':
form = OrderCreateForm(request.POST)
if form.is_valid():
order = form.save() # here I save order object
for item in cart: # and here I save ordered items
OrderItem.objects.create(
order=order,
product=item.product,
price=item.product.price,
quantity=item.quantity)
cart.clear()
return HttpResponseRedirect('%s?status_message=%s'
% (reverse('get_cart'), _('Thank you for your order!')))
else:
form = OrderCreateForm()
return render(request, 'products/make_order.html', {
'form': form})
UPDATE: I understood that I need to use
@property
def total_order_cost(self):
return self.orderitem_set.aggregate(total=Sum(F('price') * F('quantity')))['total']
But I don't now how to use it. I tried it like this, but it doesn't work:
class Order(models.Model):
total_order_cost = models.DecimalField( db_column='total_order_cost', max_digits=10, decimal_places=2, verbose_name=_('Total Order Cost'))
@property
def total_order_cost(self):
return self.orderitem_set.aggregate(total=Sum(F('price') * F('quantity')))['total']
Upvotes: 0
Views: 3757
Reputation: 22831
Unless you are running into performance problems, why store derived data at all? You could drop the total_price
field from OrderItem
and the total_order_cost
from Order
and simply query for it when needed using aggregation and F expressions. How about something like this:
@property
def total_order_cost(self):
return self.orderitem_set.aggregate(total=Sum(F('price') * F('quantity')))['total']
Upvotes: 4