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

Pau*_*ite 75 python django django-models

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

有没有办法获取查询集,或只是一个对象列表,这是每个管理器方法返回的查询集的并集?

Jor*_*ter 162

这工作,看起来更清洁:

records = query1 | query2
Run Code Online (Sandbox Code Playgroud)

如果你不想要重复,那么你需要追加.distinct():

records = (query1 | query2).distinct()
Run Code Online (Sandbox Code Playgroud)

  • records = query1 | query2; records = records.distinct()会给我正确的结果 (10认同)
  • 由于Django错误,在处理`ManyToManyField`s时,这种结构有时会返回错误的结果.例如,您有时会看到`records.count()`将大于`query1.count()+ query2.count()`,这显然是不正确的. (5认同)
  • 虽然接受的答案返回了一个union iterable(确切地说是列表),就像OP要求的那样,这个方法返回一个真正的查询集合.该查询集可以进一步操作,这在许多情况下是期望的. (4认同)
  • @Jian你可以用bug和djangoproject问题链接澄清django版本吗? (4认同)
  • 您可以在Python中重载运算符.见http://docs.python.org/2/library/operator.html.所以Django所做的是为QuerySet对象创建特殊方法.请参阅此处的代码:https://github.com/django/django/blob/master/django/db/models/query.py#L178`QuerySet`类提供调用的`__and__`和`__or__`方法当在两个`QuerySet`对象之间使用`&`或`|`运算符时(也用于`Q`类). (4认同)
  • 我很确定你不能指望它尊重现有的订单.但是,之后你可以在`final_query`上调用`order_by`.如果每个零件保持现有订单至关重要,那么您应该手动组合它们. (2认同)
  • 我认为@JordanReiter 的评论值得更多选票。重要的是要了解 ORM 将创建 OR 查询而不是 UNION 查询,因此该方法不能用于实现自定义排序。 (2认同)

Jos*_*ian 41

版本1.11开始,django querysets具有内置联合方法.

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
Run Code Online (Sandbox Code Playgroud)

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


Xia*_*ing 7

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

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

print "| result:"
for element in (query_set1 | query_set2):
    print element
Run Code Online (Sandbox Code Playgroud)

结果:

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

| result:
KafkaTopic object
KafkaTopic object
Run Code Online (Sandbox Code Playgroud)