Django分发过滤结果

时间:2017-06-20 12:52:36

标签: python django filter orm

在Django应用程序中,我正在进行如下查询:

Products.objects.filter(category_id=[1, 2, 3])[:6]

我从类别1中找回了6个项目。我想要的是每个类别2项目。

或者我尝试使用Q,如下所示:

Products.objects.filter(Q(category_id=1)|Q(category_id=2)|Q(category_id=3))[:6]

我可以获得所有结果,然后遍历结果以过滤掉,依此类推。结果查询集非常大。

如何通过单一查询使用Django ORM进行查询而无需遍历整个查询集?

1 个答案:

答案 0 :(得分:1)

我没有看到任何直接的方法。我能想到的一些解决方法:

直接迭代(1个查询):

最直接的方式,只涉及一个查询。请记住使用iterator,因此内存中没有完整的查询集。

for product in Products.objects.filter(category_id__in=[1, 2, 3]).iterator():
    # Add some logic to select your six items.

当然,根据迭代顺序,它可能很耗时(例如,如果首先插入所有类别1项目)。抛出一个随机顺序.order('?')可能有所帮助,但要注意它有一些警告(主要是它很慢)。


查询每个类别(与类别一样多的查询):

[
    p
    for category_id in [1, 2, 3]
    for p in Products.objects.filter(category_id=category_id)[:2]
]

结果不再是查询集,但这可能无关紧要。


多轮(如果你想要前两个,则有2个查询):

获取每个类别中的第一个,排除它们,然后获取第二个类别。

ids = [1, 2, 3]
items = list(Products.objects.filter(category_id__in=ids).distinct('category'))

items += list(Products.objects.filter(category_id__in=ids).exclude(
    id__in=[i.id for i in items],
).distinct('category'))

同样需要注意的是,它不再是一个列表而不是查询集,并且还会看到distinct(*field)的限制。