我有一个看起来像这样的模型:
class Item(models.Model):
name = models.CharField()
type = models.CharField()
tags = models.models.ManyToManyField(Tags)
为了呈现给定的视图,我有一个视图,它根据类型显示项目列表。因此,在我看来,有一个查询类似于:
items = Item.objects.filter(type='type_a')
所以这很简单,也很直接。现在我对视图有一个额外的要求。为了满足这个要求,我需要构建一个将标签与项目相关联的字典。所以我想要的输出应该是这样的:
{
'tag1': [item1, item2, item5],
'tag2': [item1, item4],
'tag3': [item3, item5]
}
最有效的方法是什么?有没有任何方法可以做到这一点,而不必为每个标签使用新的查询进入数据库?
您可以检查prefetch_related
,它可能会对您有所帮助:
这与
select_related
有着相似的目的,因为两者都是为了阻止由于访问相关对象而导致的数据库查询泛滥,但策略完全不同。。。另一方面,prefetch_related
对每个关系进行单独的查找,并在Python中进行"连接"。这允许它预取多对多和多对一对象,而这是使用select_related无法完成的。。。
因此,最终您将执行多个查询或使用prefetch_related
,它将对对象执行一些Python联接。
您可以这样做:
# This should require two database queries, one for the items
# and one for all the associated tags.
items = Item.objects.filter(type='type_a').prefetch_related('tags')
# Now massage the data into your desired data structure.
from collections import defaultdict
tag_dict = defaultdict(list)
for item in items:
# Thanks to prefetch_related this will not hit the database.
for tag in item.tags.all():
tag_dict[tag].append(item)