我有一个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执行单个查询来获取所有项目及其所有属性?
答案 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')