Django:重复过滤查询集的最有效方法

时间:2014-04-20 05:38:20

标签: python django django-queryset

我的模型看起来像这样:

class Item(models.Model):
    name = models.CharField()
    type = models.CharField()
    tags = models.models.ManyToManyField(Tags)

为了呈现给定的视图,我有一个视图,它根据类型显示一个Items列表。所以在我看来,有一个类似的查询:

items = Item.objects.filter(type='type_a')

这样既简单又直接。现在我对视图有了额外的要求。为了满足这个要求,我需要构建一个将Tags与Items相关联的字典。所以我正在寻找的输出将是:

{
    'tag1': [item1, item2, item5],
    'tag2': [item1, item4],
    'tag3': [item3, item5]
}

最有效的方法是什么?有没有办法在不使用每个标记的新查询进入数据库的情况下执行此操作?

2 个答案:

答案 0 :(得分:3)

您可以查看prefetch_related它可能会对您有所帮助:

  

这与select_related具有类似的目的,因为它们都旨在阻止因访问相关对象而导致的数据库查询泛滥,但策略完全不同...... prefetch_related,另一方面,对每个关系进行单独查找,并在Python中进行“连接”。这允许它预取多对多和多对一对象,这是使用select_related ...

无法完成的。

所以最后你要么做多个查询,要么使用prefetch_related,它会在对象上做一些Python连接。

答案 1 :(得分:2)

您可能会这样做:

# 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)