我在“AND”查询上发现了不同的结果,具体取决于它是否是正向查询的反向。
Model.objects.filter(x=1) & Model.objects.filter(y=2)
Model.objects.filter(x=1, y=2)
Model.objects.filter(Q(x=1) & Q(y=2))
所有结果都相同:满足两个条件(x=1 和 y=2)的 QuerySet。
我有这些型号:
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
class Author(models.Model):
name = models.CharField(max_length=100)
country = models.ForeignKey(Country, on_delete=models.CASCADE)
class Entry(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateField()
authors = models.ManyToManyField(Author)
假设我有这些数据:
标题 | 发布日期年份 | 作者 | 博客 |
---|---|---|---|
流行 1 | 2023 | 胡安 | 流行 |
流行2 | 2023 | 艾玛 | 流行 |
流行3 | 2010 | 胡安·沃尔默 | 流行 |
其他 | 2023 | 约翰 | 披头士乐队 |
预期结果:胡安和艾玛。
标题 | 发布日期年份 | 作者 | 博客 |
---|---|---|---|
流行 1 | 2023 | 胡安 | 流行 |
流行2 | 2023 | 艾玛 | 流行 |
我们可以使用以下方法:
Author.objects.filter(entry__headline__contains="Pop", entry__pub_date__year=2023)
Author.objects.filter(Q(entry__headline__contains="Pop") & Q(entry__pub_date__year=2023))
--> 这两个给出相同的答案(预期结果:Juan 和 Emma)并创建相同的 SQL:
SELECT "blog_author"."id", "blog_author"."name", "blog_author"."email", "blog_author"."country_id"
FROM "blog_author"
INNER JOIN "blog_entry_authors"
ON ("blog_author"."id" = "blog_entry_authors"."author_id")
INNER JOIN "blog_entry"
ON ("blog_entry_authors"."entry_id" = "blog_entry"."id")
WHERE ("blog_entry"."headline" LIKE %Pop% ESCAPE '\' AND "blog_entry"."pub_date" BETWEEN 2023-01-01 AND 2023-12-31)
Author.objects.filter(entry__headline__contains="Pop") & Author.objects.filter(entry__pub_date__year=2023)
结果不同,AND查询得到这个作者:Juan,Emma,Juan。 我想这也应该是:胡安和艾玛。
但为什么不是呢?
这是创建的SQL(与前两个不同)
SELECT "blog_author"."id", "blog_author"."name", "blog_author"."email", "blog_author"."country_id"
FROM "blog_author"
INNER JOIN "blog_entry_authors"
ON ("blog_author"."id" = "blog_entry_authors"."author_id")
INNER JOIN "blog_entry"
ON ("blog_entry_authors"."entry_id" = "blog_entry"."id")
LEFT OUTER JOIN "blog_entry_authors" T4
ON ("blog_author"."id" = T4."author_id")
LEFT OUTER JOIN "blog_entry" T5 ON (T4."entry_id" = T5."id")
WHERE ("blog_entry"."headline" LIKE %Pop% ESCAPE '\' AND T5."pub_date" BETWEEN 2023-01-01 AND 2023-12-31)
>>>