首页 > 解决方案 > 如何减少我的 Django 应用程序的查询量?

问题描述

我的应用程序目前正在执行 1000 多个 SQL 查询,并且需要大约 20 秒来加载页面。我似乎无法找到一种方法来提出解决方案,以更快地在我的模板中的表格上显示相同的数据。我不想显示 100 个结果,所以我的分页设置为 100。

这些是我的models.py 中用于获取订单数量和总和的方法,这两个在我的 Company 模型中,get_order_count 也在我的 Contact 模型中

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

视图.py

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">&nbsp;</th>
            <td>{{ contact.first_name }} {{ contact.last_name }}</td>
            <td id="contact-orders">
                Orders: {{ contact.get_order_count }} 
            </td>
            <td></td>
        </tr>
    {% endfor %}
{% endfor %}

标签: pythondjango

解决方案


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 }}.


推荐阅读