如何找到两个Django查询集的并集?


92

我有一个带有两个自定义管理器方法的Django模型。每个对象都基于对象的不同属性返回模型对象的不同子集。

有没有什么方法可以获取一个查询集,或者仅仅是一个对象列表,那就是每个管理器方法返回的查询集的并集?


3
(来自已删除的答案)有关适用于不同模型的QuerySet的变体,请参见以下问题:stackoverflow.com/questions/431628/…–
rnevius

1
从版本1.11开始,Django查询集具有内置的联合方法。我已将其添加为答案供以后参考
Jose Cherian

Answers:


179

这可以工作,看起来更干净:

records = query1 | query2

如果您不希望重复,则需要添加.distinct()

records = (query1 | query2).distinct()

5
正如OP所要求的那样,虽然接受的答案返回一个可迭代的并集(确切地说是列表),但此方法返回的是查询集的真正并集。此查询集可以进一步操作,这在许多情况下都是需要的。
Krystian Cybulski 2013年

5
由于Django错误,这种构造有时在处理ManyToManyFields时可能返回错误的结果。例如,您有时会看到该records.count()值大于query1.count() + query2.count(),这显然是不正确的。

4
@Jian您可以使用该错误以及djangoproject问题的链接来阐明django版本吗?
IMFletcher

10
记录= query1 | query2; records = records.distinct()会给我正确的结果
eugene

5
您可以在Python中重载运算符。请参阅docs.python.org/2/library/operator.html。因此,Django要做的是为QuerySet对象创建特殊的方法。看到这里的代码:github.com/django/django/blob/master/django/db/models/...QuerySet类提供方法__and____or__被调用的时候,&或者|运营商两者之间的使用QuerySet对象(也可用于Q类以及)。
Jordan Reiter 2013年

49

版本1.11开始,Django查询集具有内置的联合方法。

q = q1.union(q2) #q will contain all unique records of q1 + q2
q = q1.union(q2, all=True) #q will contain all records of q1 + q2 including duplicates
q = q1.union(q2,q3) # more than 2 queryset union

有关更多示例,请参见我的博客文章


我无法全力以赴=正确工作。最后将我的查询集强制转换为一个集,然后再将其返回给客户端。
布雷登·霍尔特

1
@ BradenHolt,all = True,表示它将包含重复的记录。您可以简单地删除all = True以避免将其强制转换为集合。
Jose Cherian

在这不起作用DjangoFilterBackend后,如何使用union和DjangoFilterBackend?
nesalexy

不幸的是,这似乎不适用于在模型的Meta中定义了默认顺序的模型。每当我尝试将它们与.union组合时,都会出现以下错误:“复合语句的子查询中不允许ORDER BY。”
jrial

4

我建议使用'query1.union(query2)'代替'query1 | query2'; 我从以上两种方法中得到了不同的结果,而前一种是我所期望的。以下是我遇到的内容:

print "union result:"
for element in query_set1.union(query_set2):
    print element

print "| result:"
for element in (query_set1 | query_set2):
    print element

结果:

union result:
KafkaTopic object
KafkaTopic object
KafkaTopic object
KafkaTopic object
KafkaTopic object

| result:
KafkaTopic object
KafkaTopic object

1
请粘贴代码,而不是代码图像。图片中的文本不可搜索,您无法将其复制/粘贴到编辑器中进行验证,并且占用了多余的空间。使用反引号将代码标记为代码,以便正确格式化。请参阅文本输入框旁边的“帮助”链接。
jrial

感谢您的更新。:)
jrial
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.