Django查询集效率

时间:2014-11-13 03:14:36

标签: python django django-queryset

我有一个Item对象,它对Receipt个对象有一个ForeignKey。

class Receipt(models.Model):
    ...

class Item(models.Model):
    receipt = models.ForeignKey(Receipt)
    name = models.CharField(max_length=255)
    cost = models.DecimalField(default=0, max_digits=6, decimal_places=3)

    ...

我使用通用视图显示收据。

class ReceiptView(DetailView):
    model = Receipt

然后在模板上,我想在收据上显示所有项目。

<ul>
{% for item in object.item_set.all %}
    <li>{{ item.name }}</li>
{% endfor %}
</ul>

这适用于较小的数据集。其中一个收据对象有1600个与之相关的项目。加载该收据的页面非常慢。使用Django调试工具栏我注意到Django每个项目正在执行1个查询。

如果我改变模板中的列表项,而不是显示项目的属性,我只显示项目本身,Django只执行一个查询。

<ul>
{% for item in object.item_set.all %}
    <li>{{ item }}</li>
{% endfor %}
</ul>

不幸的是,我需要在模板中显示大约10个项目的属性。有没有我可以告诉Django执行单个查询来获取所有项目及其所有属性?

1 个答案:

答案 0 :(得分:1)

使用prefetch_related。由于您正在进行反向外键查找,因此您基本上使用的是ManyToMany关系。 prefetch_related将在幕后进行单独查询,以便为您检索并缓存所有Receipt个对象。

由于您使用的是通用视图,而不是指定model,因此您可以指定queryset

class ReceiptView(DetailView):
    queryset = Receipt.objects.prefetch_related('related_items')

要执行此操作,您必须在related_name模型中指定Item

class Item(models.Model):
    receipt = models.ForeignKey(Receipt, related_name='related_items')