过滤django queryset以仅包含给定列表中的结果

时间:2012-01-09 12:35:26

标签: django

所以我在Django制作了一个'配方'Web应用程序,我有一个名为“用户的橱柜”的功能,用户可以在其中添加任何成分,他将会看到一个名为'Makeable recipes'的选项,其中应用程序会建议用户根据其内阁的成分可以制作哪些食谱。现在的问题是,如果我希望食谱中包含任何成分,我可以做'Recipe.objects.filter(ingredients _in = cabinet_ingredients)。如果我想过滤机柜中的所有配料,我可以这样做:

qs = Recipe.objects.annotate(count=Count('ingredients'))\
                .filter(count=len(cabinet_ingredients))
for ingredient in cabinet_ingredients:
    qs = qs.filter(ingredients=ingredient)

但是,如果我想要一个橱柜成分的子集(这更有意义),这样食谱不应包含这些成分之外的任何东西,并且可以包含此列表中的任何内容。例如,考虑到3种橱柜成分,'foo','bar','baz',我必须找到具有以下结果的食谱:

Recipes with 3 ingredients:
('foo', 'bar', 'baz')
Recipes with 2 ingredients:
('foo', 'bar'), 
('foo', 'baz'),
('bar', 'baz')
Recipes with single ingredient:
('foo')
('bar')
('baz')

这有什么线索?提前谢谢。

2 个答案:

答案 0 :(得分:3)

假设你有一张食谱表,你可以这样做:

# ingredients _not_ in the cabinet
inner_qs = Ingredient.objects.exclude(name__in = cabinet_ingredients)
# recipes that do not contain an ingredient that is _not_ in the cabinet
qs = Recipe.objects.exclude(ingredients__in = inner_qs)

答案 1 :(得分:0)

@cha0site的回答大多是正确的。但是,这将导致对数据库的两个查询,而只需要一个查询。请改用以下方法:

from django.db.models import Q
Recipe.objects.exclude(~Q(ingredients__name__in=cabinet_ingredients))