gpt4 book ai didi

django - 更改 Q 对象顺序的查询结果不同

转载 作者:行者123 更新时间:2023-12-02 21:44:05 25 4
gpt4 key购买 nike

我在使用 Q 对象创建查询集时遇到问题。根据我订购某些 Q 条件的方式,我会得到不同的结果。我将稍微简化我的模型,以便以干净的方式描述我的问题。

class D(models.Model):
one_attr = models.BooleanField()
s_attr = models.ManyToManyField(S, through='DRelatedToS')
d_to_p = models.ForeignKey(P)


class S(models.Model):
other_attr = models.BooleanField()
s_to_p = models.ForeignKey(P)


class DRelatedToS(models.Model):
to_s = models.ForeignKey(S)
to_d = models.ForeignKey(D)
date = models.DateField()


class P(models.Model):
the_last_attr = models.PositiveIntegerField()

关系总结:

D <-- DRelatedToS --> S --> P
| ^
| |
-------->------->------>----^

通过这些模型和关系,根据我如何安排 Q 条件,我得到两个不同的结果:第一个查询,给出一个结果

D.objects.filter(
Q(one_attr=True, s_attr__s_to_p__the_last_attr=5)
|
Q(one_attr=False, d_to_p__the_last_attr=10)
)

第二个查询,给出另一个结果,与第一个查询不同

D.objects.filter(
Q(one_attr=False, d_to_p__the_last_attr=10)
|
Q(one_attr=True, s_attr__s_to_p__the_last_attr=5)
)

我的问题是:为什么会发生这种情况?我的查询方式有什么问题吗?

当我观察从这些查询派生的 SQL 语句时,我得到两个不同的语句:一个生成 LEFT OUTER JOIN 和许多 INNER JOIN 以及第二个组成所有INNER JOIN。真正返回我想要的内容的是创建LEFT OUTER JOIN的那个。这让我觉得我的所有查询都可能返回不好的结果,具体取决于我如何安排其条件。这是一个错误还是我做错了什么(或所有事情)?

最佳答案

在您的示例中,不同的顺序应该返回相同的结果。

尽管如此,我测试了您的代码(使用我在问题代码中所做的更正),但无法生成您所描述的错误。也许您在简化代码时引入了其他错误并错过了,您可以发布您使用的示例数据吗? (请参阅下面的我的数据)。

首先,您的示例代码有错误,我编辑了您的问题,建议进行以下更正来解决问题、简化和改进测试,但我没有看到更新的更改,因此我在此处重复:

更正 1: diff 格式的模型更改:

3,4c6,10
< s_attr = models.ManyToMany(S, through='DRelatedToS')
< d_to_p = models.ForeignKey(P)
---
> s_attr = models.ManyToManyField('S', through='DRelatedToS')
> d_to_p = models.ForeignKey('P')
>
> def __unicode__(self):
> return 'D:(%s,%s,%s)' % (self.id, self.one_attr, self.d_to_p.the_last_attr)
8,9c14
< other_attr = models.BooleanField()
< s_to_p = models.ForeignKey(P)
---
> s_to_p = models.ForeignKey('P')
13d17
< to_p = models.ForeignKey(P)
15c19
< date = models.DateField()
---
> to_s = models.ForeignKey(S)
19a24
>

所以应用修正后模型看起来像这样:

class D(models.Model):
one_attr = models.BooleanField()
s_attr = models.ManyToManyField('S', through='DRelatedToS')
d_to_p = models.ForeignKey('P')

def __unicode__(self):
return 'D:(%s,%s,%s)' % (self.id, self.one_attr, self.d_to_p.the_last_attr)


class S(models.Model):
s_to_p = models.ForeignKey('P')


class DRelatedToS(models.Model):
to_d = models.ForeignKey(D)
to_s = models.ForeignKey(S)


class P(models.Model):
the_last_attr = models.PositiveIntegerField()

更正 2:查询中的查找字段错误(已在答案中修复)。

以下是我所做的:

  1. 创建名为 testso 的项目和应用:

    django-admin.py startproject marianobianchi
    cd marianobianchi
    python manage.py startapp testso
  2. 添加模型并调整项目设置(数据库设置,将 testso 添加到 INSTALLED_APPS)

  3. 添加示例数据:

    mkdir testso/fixtures
    cat > testso/fixtures/initial_data.json
    [
    {"pk": 1, "model": "testso.d", "fields": {"one_attr": true, "d_to_p": 3}},
    {"pk": 2, "model": "testso.d", "fields": {"one_attr": true, "d_to_p": 4}},
    {"pk": 3, "model": "testso.d", "fields": {"one_attr": false, "d_to_p": 5}},
    {"pk": 4, "model": "testso.d", "fields": {"one_attr": false, "d_to_p": 5}},

    {"pk": 1, "model": "testso.s", "fields": {"s_to_p": 1}},
    {"pk": 2, "model": "testso.s", "fields": {"s_to_p": 2}},
    {"pk": 3, "model": "testso.s", "fields": {"s_to_p": 3}},

    {"pk": 1, "model": "testso.drelatedtos", "fields": {"to_d": 2, "to_s": 1}},
    {"pk": 2, "model": "testso.drelatedtos", "fields": {"to_d": 1, "to_s": 2}},
    {"pk": 3, "model": "testso.drelatedtos", "fields": {"to_d": 1, "to_s": 3}},

    {"pk": 1, "model": "testso.p", "fields": {"the_last_attr": 5}},
    {"pk": 2, "model": "testso.p", "fields": {"the_last_attr": 5}},
    {"pk": 3, "model": "testso.p", "fields": {"the_last_attr": 3}},
    {"pk": 4, "model": "testso.p", "fields": {"the_last_attr": 4}},
    {"pk": 5, "model": "testso.p", "fields": {"the_last_attr": 10}}
    ]
  4. python manage.pysyncdb

  5. python manage.py shell
  6. 在外壳中:

    >>> from testso.models import *
    >>> from django.db.models import Q
    >>> D.objects.filter(Q(one_attr=True, s_attr__s_to_p__the_last_attr=5) | Q(one_attr=False, d_to_p__the_last_attr=10))
    [<D: D:(1,True,3)>, <D: D:(2,True,4)>, <D: D:(3,False,10)>, <D: D:(4,False,10)>]
    >>> D.objects.filter(Q(one_attr=False, d_to_p__the_last_attr=10) | Q(one_attr=True, s_attr__s_to_p__the_last_attr=5))
    [<D: D:(1,True,3)>, <D: D:(2,True,4)>, <D: D:(3,False,10)>, <D: D:(4,False,10)>]

同样的结果! ...正如预期的那样。

关于django - 更改 Q 对象顺序的查询结果不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19840561/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com