How can I find the union of two Django querysets?
我有一个带有两个自定义管理器方法的django模型。每个返回模型对象的不同子集,基于对象的不同属性。
有没有办法得到一个查询集,或者只是一个对象列表,这是每个管理器方法返回的查询集的联合?
- (从已删除的答案中)有关不同模型的查询集的变体,请参阅此问题:stackoverflow.com/questions/431628/…
- 从1.11版开始,Django查询集有一个内置的联合方法。我已经加了它作为将来参考的答案
这很有效,看起来更干净:
1
| records = query1 | query2 |
如果不需要重复,则需要追加.distinct():
1
| records = (query1 | query2).distinct() |
号
- 虽然接受的答案返回union iterable(确切地说是list),就像op所要求的那样,这个方法返回一个查询集的真正联合。这个查询集可以进一步操作,在许多情况下都是需要的。
- 由于django错误,这种构造在处理ManyToManyFields时有时会返回不正确的结果。例如,有时您会看到records.count()将大于query1.count() + query2.count(),这显然是不正确的。
- @Jian你能用这个bug解释一下django版本并链接到djangoproject问题吗?
- @imfletcher:我有1.4.5和all=my_instance.forward_many to_many.all()my_instance.reverse_many to_many.all()都有重复条目,我认为union应该消除重复条目。
- records=query1 query2;records=records.distinct()将给出正确的结果
- 这是怎么工作的?我们知道""是位或。那么,query1 query2是如何工作的呢?它是否需要一点query1和query2的表示?
- 可以在python中重载操作符。请参见docs.python.org/2/library/operator.html。所以Django所做的就是为queryset对象创建特殊的方法。参见这里的代码:github.com/django/django/blob/master/django/db/models/…QuerySet类为__and__和__or__提供方法,这些方法在两个QuerySet对象之间使用&或|操作符时调用(也用于Q类)。
- 这个联合是否尊重查询集的原始顺序?如果我执行final_query = query1 | query2,最终的查询将是一个queryset,其中首先是query1的元素,然后是query2的元素(不在query1中)?
- 我很肯定你不能指望它能遵守现有的订单。但是,您可以在之后的final_query上给order_by打电话。如果每个部分保持其现有的顺序是至关重要的,那么您应该手动组合它们。
- 我认为@jordanreiter的评论值得更多的投票。重要的是要理解ORM将创建一个或查询而不是联合查询,这样方法就不能用于实现自定义排序。
- @尤金关于需要打电话给queryset.distinct()才能得到明显结果的评论应该加到答案中。我有一个错误,结果不明显,所以需要调用这个错误。
- 这不在django docs(docs.djangoproject.com/en/1.10/topics/db/queries)中,是否已弃用?
- @我不知道为什么不在医生那里。据我所知,它在姜戈1.10仍然有效。这是实现它的源的直接链接:github.com/django/django/blob/master/django/db/models/…
从1.11版开始,Django查询集有一个内置的联合方法。
1 2 3
| 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 |
有关更多示例,请参阅我的博客文章。
- 我不能全力以赴工作。最后将我的查询集强制转换为一个集,然后将其返回到客户端。
- @bradenholt,all=true,表示它将包含重复的记录。您可以简单地删除all=true以避免将其强制转换为集合。