【问题标题】:ADDing Django's Q() objects and get two exclusive JOIN ONs添加 Django Q() 对象并获得两个独占的 JOIN ON
【发布时间】:2015-08-05 17:50:34
【问题描述】:

所以这就是场景:

class Person(models.Model):
    ...
class Aktion(models.Model):
    ...

class Aktionsteilnahme(models.Model):
    person = models.ForeignKey(Person)
    aktion = models.ForeignKey(Aktion)

现在的问题是,我正在基于Q()-objects 动态构建相当复杂的查询。他们最终是这样的:

Person.objects.filter(
    Q((Q()|Q(aktionsteilnahme__aktion=302))&
    (Q()|Q(aktionsteilnahme__aktion=547)))
)

可以(并且会自动)简化为:

Person.objects.filter(
    Q(aktionsteilnahme__aktion=302)&
    Q(aktionsteilnahme__aktion=547)
)

现在的问题是,这会导致这样的 SQL:

SELECT * FROM person
LEFT OUTER JOIN aktionsteilnahme ON ( person.id = aktionsteilnahme.person_id )
WHERE (aktionsteilnahme.aktion = 2890 AND aktionsteilnahme.aktion = 5924)

然而我真正需要的是:

Person.objects.filter(Q(aktionsteilnahme__aktion=302))
    .filter(Q(aktionsteilnahme__aktion=547))

导致我真正需要的东西:

SELECT * FROM person
INNER JOIN aktionsteilnahme ON ( person.id = aktionsteilnahme.person_id )
INNER JOIN aktionsteilnahme T4 ON ( person.id = T4.person_id )
WHERE (aktionsteilnahme.aktion = 302 AND T4.aktion = 547)

我不能使用建议的解决方案,因为所有这些都将再次被OR'ed。

我必须能够做类似的事情:

Person.objects.filter(
    Q(
      Q(aktionsteilnahme__aktion=302))
      .filter(Q(aktionsteilnahme__aktion=547))
    )
    |
    Q(other_q_filters)
)

【问题讨论】:

    标签: django django-queryset django-q


    【解决方案1】:

    在摆弄了更多之后,我意识到:Django QuerySets 可以是OR'ed。

    因此,我现在的解决方案是创建如下内容:

    Person.objects.filter(Q(aktionsteilnahme__aktion=302))
          .filter(Q(aktionsteilnahme__aktion=547))
    |
    Person.objects.filter(Q(other_q_filters))
    

    现在所有内部的ANDs 都使用过滤器连接起来,最外面的ORs 是直接在查询集上的布尔值|

    请注意!由于内部子查询总是被完全评估(不再有“限制 20”),请求变得慢得多OR-ing QuerySets 将导致多个条目 - 所以最终

    (QuerySet | QuerySet | QuerySet).distinct()
    

    通常是必要的。

    【讨论】:

      猜你喜欢
      • 2012-02-18
      • 2011-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-13
      • 2020-06-07
      • 2013-05-30
      相关资源
      最近更新 更多