Django:循环查询并返回最新的相关对象

时间:2016-10-23 15:36:17

标签: django django-views

我的应用中Unit每周都会创建OrderReport,我希望在第一列中查看结果为包含Unit s名称的表格在接下来的6列中有3个最新的OrderReport s。所以我需要查询单位和3个相关的订单和报告到每个单位。 我尝试以这种方式使用prefetch_related,但不知道如何限制它(甚至让它工作)

Unit.objects.filter(parent__name__contains="x").prefetch_related('order_set', 'reportfrom_set').order_by('order__date','reportfrom__submit_datetime')

提前致谢

1 个答案:

答案 0 :(得分:0)

prefetch_related()方法将为您要预取的每个查找执行数据库查询。基本上,在这里,Django将执行第一个数据库查询以获取Unit个实例,然后执行另外两个查询以获取OrderReport实例。

因此,一旦执行了Unit.obects.filter(...).prefetch_related(...)查询集,每个Unit实例将缓存其相关的OrderReport对象(不再需要数据库查询来获取这些数据)。

views.py

自Django 1.7起,prefetch_related()方法接受Prefetch对象。此Prefetch对象具有queryset属性,可帮助您过滤/订购相关对象:

from django.shortcuts import render_to_response

def my_view(request):
    units = Unit.objects.all().prefetch_related(
        Prefetch(
            'orders_set',
            queryset=Order.objects.all().order_by('date'),
            to_attr='prefetched_orders'
        ),
        Prefetch(
            'report_set',
            queryset=Report.objects.all().order_by('submit_datetime'),
            to_attr='prefetched_reports'
        )
    )

    for unit in units:
        unit.prefetched_orders = unit.prefetched_orders[:3]
        unit.prefetched_reports = unit.prefetched_reports[:3]

    return render_to_response('template.html', context={
        'units': units
    })

to_attr属性允许我们将相关对象存储在Python list中。 因此,slicing这些列表将不再调用数据库。

现在您拥有最新的订单和报告,您可以构建所需的对象。

template.html

您可以像这样迭代你的单位(units集合是模板上下文的units对象):

{%  for unit in units %}
    ...
{% endfor %}

然后,您可以浏览以前预取的对象(使用此代码的表格设计):

<table>
{%  for unit in units %}
    <tr>
        <td>{{ unit.field_to_display }}</td>
        {% for order in unit.prefetched_orders %}
            <td>{{ order.field_to_display}}</td>
        {% endfor %}

        {% for report in unit.prefetched_reports %}
            <td>{{ report.field_to_display}}</td>
        {% endfor %}
    </tr>
{% endfor %}
</table>

有关模板语言的更多信息,请参阅official doc