【问题标题】:simple way for QuerySet union and subtraction in django?django中QuerySet联合和减法的简单方法?
【发布时间】:2011-02-27 19:26:26
【问题描述】:

考虑同一类的两个 QuerySet 对象。 有没有一种简单的方法可以通过计算并集将它们统一为单个 QuerySet? 另外,有没有一种简单的方法来减去它们?从其中一个集合中删除出现在两个集合中的所有元素?

【问题讨论】:

  • 我们能否举一些例子来说明如何生成最初的两个 QuerySet 以及如何使用它们?有了更多信息,您也许可以简单地优化您的原始 QuerySet 而不必添加/减去?
  • qs1 = MyObj1.objects.filter(some_field__gte=value) - 另一方面,qs2 实际上是某个 MyObj2 实例和 MyObj1 实例之间的 M2M 关系我想我会问 QuerySets,因为我认为答案也适用于 myobj2_instance.myobj1。

标签: django django-queryset


【解决方案1】:
qs3 = qs1.union(qs2) # union
qs4 = qs1.difference(qs2) # subtraction

【讨论】:

    【解决方案2】:

    从 Django 1.11 开始,QuerySet 具有 union()intersection()difference() 方法。

    还可以将&| 运算符与QuerySets 一起使用(我在文档中找不到对此的引用,所以我猜union()intersection() 是组合两个查询集的首选方式。

    qs3 = qs1.union(qs2)         # or qs3 = qs1 | qs2
    qs3 = qs1.intersection(qs2)  # or qs3 = qs1 & qs2
    qs3 = qs1.difference(qs2)    # the ^ operator is not implemented.
    

    您还可以使用Q() 对象,如QuerySets 实现|&,另外还有反转运算符~

    【讨论】:

      【解决方案3】:

      使用相同的模型从另一个 QuerySet 中减去一个 QuerySet。

      这行得通 - 但可能很慢

      queryset_with_hello = Blog.objects.filter(name__icontains='hello')
      queryset_without_hello = Blog.objects.exclude(pk__in=queryset_with_hello)
      

      阅读 django 文档中的性能注意事项:

      https://docs.djangoproject.com/en/dev/ref/models/querysets/#in

      【讨论】:

      • 这仅在构造查询集时有效,问题是关于现有查询集。当 qs1-qs2 已经作为查询集存在时,他们将如何进行。
      • 修改现有查询集是一个在 django 中没有多大意义的概念。这样做:q = Blog.objects.filter(pk__in=q1).exclude(pk__in=q2)
      • @DylanYoung 为什么? AFAIK 这是有道理的,因为只有在您对其进行迭代或明确调用其中一种方法时才会评估查询集 docs.djangoproject.com/en/2.1/ref/models/querysets/… 所以这个答案很有意义。
      • @Qback 是的,答案是有道理的;请看一下我回复的评论。关键是:它不是在修改现有的 QuerySet(一个没有多大意义的概念:大多数对现有查询集的调用都会返回一个 new 查询集)。 @Curtwagner1984 也就是说,使用现有的查询集 q1q2,您可以使用与此答案给出的基本相同的代码获得表示差异的查询集:q_diff = q1.exclude(pk__in=q2)
      【解决方案4】:

      回到django's documentation,你可以:

      new_query_set = query_set_1 | query_set_2
      

      这就像一个逻辑或,实际上是没有重复的加法。这回答了加法方面,并且 AFAIK 根本没有击中数据库

      new_query_set = query_set_1 & query_set_2
      

      这可以作为逻辑 AND。

      仍然缺少如何减去查询集。我很难相信社区没有优雅地处理这件事......

      【讨论】:

      • 仍在寻找减去查询集的 calssy 方法
      【解决方案5】:

      您可以使用Q object

      语法可能是这样的:

      added_query_set = YourModel.objects.\
               filter(Q(id__in=old_query_set_1)|Q(id__in=old_query_set_2))
      

      您可能可以根据您的实际需求进行优化并降低 db 命中数(现在是 3),但这应该可以帮助您入门。

      【讨论】:

      • +1 用于很好地处理查询集,但我想它甚至比添加列表还要多一次访问数据库!我猜你喜欢哪种方法取决于你是想要一个未评估的 qs 还是更少的 db hits!
      • 鉴于两个原始 QuerySets 的实际参数,您应该能够将这些参数包含在 Q 对象中并降低到一个 db hit
      【解决方案6】:

      我认为您需要对运营进行评估。所以你可以对它们调用list(),并使用常见的python列表操作来处理它们!

      【讨论】:

      • 请不要:(
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-13
      • 1970-01-01
      • 2021-06-24
      • 1970-01-01
      • 1970-01-01
      • 2021-08-28
      • 2012-01-09
      相关资源
      最近更新 更多