Reputation: 23
My app is currently making over 1000 SQL queries and taking around 20s to load the page. I can't seem to find a way to come up with a solution to get the same data displayed on a table in my template faster. I wan't to display 100 results so that's way my pagination is set to 100.
These are the methods in my my models.py used to get the count and sum of the orders, these two are in my Company model and the get_order_count is also in my Contact model
def get_order_count(self):
orders = 0
for order in self.orders.all():
orders += 1
return orders
def get_order_sum(self):
total_sum = 0
for contact in self.contacts.all():
for order in contact.orders.all():
total_sum += order.total
return total_sum
class IndexView(ListView):
template_name = "mailer/index.html"
model = Company
paginate_by = 100
{% for company in company_list %}
<tr id="company-row">
<th id="company-name" scope="row">{{ company.name }}</th>
<td>{{ company.get_order_count }}</td>
<td id="order-sum">{{ company.get_order_sum|floatformat:2 }}</td>
<td class="text-center">
<input type="checkbox" name="select{{company.pk}}" id="">
</td>
</tr>
{% for contact in company.contacts.all %}
<tr id="contact-row">
<th scope="row"> </th>
<td>{{ contact.first_name }} {{ contact.last_name }}</td>
<td id="contact-orders">
Orders: {{ contact.get_order_count }}
</td>
<td></td>
</tr>
{% endfor %}
{% endfor %}
Upvotes: 0
Views: 105
Reputation: 599470
Your two methods are very inefficient. You can replace them with annotations which calculate everything in one query in the database. You haven't shown your models, but it would be something like:
class IndexView(ListView):
template_name = "mailer/index.html"
model = Company.objects.annotate(order_count=Count('orders')).annotate(order_sum=Sum('contacts__orders__total'))
paginate_by = 100
Now you can access {{ company.order_count }}
and {{ company.order_sum }}
.
Upvotes: 8