Reputation: 9682
In my Django app, I have a very repetitive query calling for item in self.schemaitem_set.all()
very often. I feel this code is vastly inefficient. I am looking for a way to cash the query. Do you guys know how I could make the code below better?
@property
def gross(self):
gross_sum = Decimal('0')
for item in self.schemaitem_set.all():
gross_sum += item.gross
return gross_sum
@property
def net(self):
net_sum = Decimal('0')
for item in self.schemaitem_set.all():
net_sum += item.net
return net_sum
@property
def deposit(self):
deposit_sum = Decimal('0')
for item in self.schemaitem_set.all():
deposit_sum += item.deposit
return deposit_sum
@property
def service_cost(self):
service_cost = Decimal('0')
if self.net > Decimal('150'):
pass
else:
service_cost += Decimal('9.99')
return service_cost
@property
def service_cost_vat(self):
service_cost_vat = Decimal('0')
if self.net > Decimal('150'):
pass
else:
service_cost_vat += Decimal(f'{9.99*0,19}')
return service_cost_vat
@property
def vat(self):
vat = Decimal('0')
for item in self.schemaitem_set.all():
vat += item.vat
return vat
Upvotes: 1
Views: 226
Reputation: 16032
You can use aggregates for this:
from django.db.models import Sum
@property
def gross(self):
return self.schemaitem_set.all().aggregate(Sum('gross'))
Now, the computation is done at the database level, and only the sum of the columns is queried.
If you constantly perform these methods together on the same template, you can reduce them to one query:
def get_aggregate_data(self):
qs = self.schematem_set.all(
).aggregate(Sum('gross'), Sum('net'), Sum('deposit'), Sum('vat'))
qs.service_cost, qs.service_cost_vat = (Decimal('9.99'), Decimal(f'{9.99*0,19}')) if qs.net > Decimal('150') else (Decimal('0'), Decimal('0'))
return qs
You can access the aggregates in your template like this:
{{ qs.price__gross }}
{{ qs.price__net }}
{{ qs.service_cost }}
Upvotes: 1