【问题标题】:How can I find the union of two Django querysets?如何找到两个 Django 查询集的联合?
【发布时间】:2011-05-23 14:25:58
【问题描述】:

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

有没有办法获得一个查询集,或者只是一个对象列表,即每个管理器方法返回的查询集的联合?

【问题讨论】:

  • (来自已删除的答案)有关适用于不同模型的 QuerySet 的变体,请参阅此问题:stackoverflow.com/questions/431628/…
  • 从 1.11 版本开始,django 查询集有一个内置的 union 方法。我已将其添加为将来参考的答案

标签: python django django-models


【解决方案1】:

这很有效,看起来更干净:

records = query1 | query2

如果您不想重复,则需要附加 .distinct():

records = (query1 | query2).distinct()

【讨论】:

  • 虽然接受的答案返回一个可迭代的联合(确切地说是列表),就像 OP 所要求的那样,但此方法返回一个真正的查询集联合。这个查询集可以进一步操作,这在许多情况下都是需要的。
  • 由于 Django 错误,在处理 ManyToManyFields 时,此构造有时会返回错误结果。例如,您有时会看到records.count() 会大于query1.count() + query2.count(),这显然是不正确的。
  • @Jian 你能用错误和 djangoproject 问题的链接澄清 django 版本吗?
  • 记录 = 查询 1 |查询2; records = records.distinct() 会给我正确的结果
  • 您可以在 Python 中重载运算符。见docs.python.org/2/library/operator.html。所以 Django 所做的就是为 QuerySet 对象创建特殊的方法。请参阅此处的代码:github.com/django/django/blob/master/django/db/models/… QuerySet 类为 __and____or__ 提供方法,当 &| 运算符用于两个 QuerySet 对象(也用于 @ 987654335@ 类)。
【解决方案2】:

version 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

有关更多示例,请参阅我的blog post

【讨论】:

  • 我无法让 all=True 工作。最终将我的查询集转换为一组,然后再将其返回给客户端。
  • @BradenHolt, all=True,表示它将包含重复记录。您可以简单地删除 all=True 以避免将其转换为集合。
  • 在这不起作用 DjangoFilterBackend 之后,我如何使用 union 和 DjangoFilterBackend ?
  • 不幸的是,这似乎不适用于在模型的 Meta 中定义了默认排序的模型。每当我尝试将这些与 .union 结合使用时,都会收到以下错误:“复合语句的子查询中不允许使用 ORDER BY。”
【解决方案3】:

我建议使用 '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

结果:

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

| result:
KafkaTopic object
KafkaTopic object

【讨论】:

    猜你喜欢
    • 2011-05-23
    • 2019-08-11
    • 2019-12-04
    • 2017-12-04
    • 2014-11-11
    • 1970-01-01
    • 2017-06-04
    • 2023-03-27
    • 2014-02-23
    相关资源
    最近更新 更多