# will return all Model with m2m field 1
Model.objects.filter(m2m_field=1)
# will return Model with both 1 AND 2
Model.objects.filter(m2m_field=1).filter(m2m_field=2)
# this will NOT work
Model.objects.filter(Q(m2m_field=1) & Q(m2m_field=2))
class Blog(models.Model):
blog_id = models.CharField()
class Post(models.Model):
blog_id = models.ForeignKeyField(Blog)
title = models.CharField()
pub_year = models.CharField() # Don't use CharField for date in production =]
SELECT *
FROM "Book"
INNER JOIN ("Post" ON "Book"."id" = "Post"."book_id")
WHERE "Post"."Title" = 'Title A'
AND "Post"."Public_Year" = '2020'
“筛选链”数据库查询使用**“T1”.“Public_Year”= '2020'**标识公共年份
SELECT *
FROM "Book"
INNER JOIN "Post" ON ("Book"."id" = "Post"."book_id")
INNER JOIN "Post" T1 ON ("Book"."id" = "T1"."book_id")
WHERE "Post"."Title" = 'Title A'
AND "T1"."Public_Year" = '2020'
class Book(models.Model):
author = models.ForeignKey(Author)
name = models.ForeignKey(Region)
class Author(models.Model):
name = models.ForeignKey(Region)
9条答案
按热度按时间20jt8wwn1#
正如您在生成的SQL语句中所看到的,不同之处并不在于“OR”,而在于WHERE和JOIN的放置方式。
范例1(相同的链接数据表):来自https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships
这将给予你所有的博客,有一个条目与
(entry__headline__contains='Lennon') AND (entry__pub_date__year=2008)
,这是你会期望从这个查询。结果:
示例2(链接)
这将覆盖示例1中的所有结果,但它会生成更多的结果,因为它首先过滤所有带有
(entry__headline__contains='Lennon')
的博客,然后从结果中过滤(entry__pub_date__year=2008)
。不同之处在于,它还将为您提供以下结果:
一个博客包含多个条目
当评估第一个筛选器时,由于第一个条目而包含图书(即使它具有其他不匹配的条目)。当评估第二个筛选器时,由于第二个条目而包含图书。
**一个表:**但是如果查询不涉及连接表,如Yuji和DTing的示例。结果是相同的。
t1rydlwq2#
“多参数筛选查询”的结果不同于“链接筛选查询”的情况如下:
基于引用对象和关系选择被引用对象是一对多(或多对多)的。
多个筛选器:
链接筛选器:
两个查询可以输出不同的结果:
如果引用模型
Referencing1
中的多行可以引用被引用模型Referenced
中的同一行,则Referenced
中可能出现这种情况:Referencing1
具有1:N(一对多)或N:M(多对多)关系。示例:
考虑我的应用程序
my_company
有两个模型Employee
和Dependent
。my_company
中的雇员可以有多个依赖项(换句话说,依赖项可以是单个雇员的儿子/女儿,而雇员可以有多个儿子/女儿)。嗯,假设像丈夫和妻子都不能工作在一个
my_company
。我举了一个1:m的例子因此,
Employee
是被引用模型,它可以被多个Dependent
引用模型引用。从属
a1
引用雇员A
,从属b1, b2
引用雇员B
。现在我的疑问是:
查找所有子女在大学和学校都有优异成绩(比如〉= 75%)的员工?
产出为'A'从属项'a1'在学院和学校中都有区别标记,它从属于员工'A'。未选择附注'B',因为'B'的子代在学院和学校中都有区别标记。关系代数:
员工****(学校标志〉=75 AND大学标志〉=75)家属
在Second中,如果我需要查询:
是否查找其部分家属在大学和学校中具有特殊标记的所有员工?
这次也选择了'B',因为'B'有两个孩子(不止一个!),一个在学校'b1'有优异成绩,另一个在大学'b2'有优异成绩。
过滤器的顺序无关紧要,我们也可以将上面的查询写成:
结果相同!关系代数可以是:
(雇员****(学校标志〉=75)家属)****(大学标志〉=75)家属
注意以下事项:
输出相同的结果:x1米15英寸
我检查Django使用
print qd1.query
和print qd2.query
生成的目标SQL查询是否相同(Django 1.6)。但是从语义上来说,两者对 me 来说是不同的。第一个看起来像简单的section σ[school_mark〉= 75 AND college_mark〉= 75](Dependent),第二个像缓慢的嵌套查询:σ[学校分数〉= 75](σ[大学分数〉= 75](依赖))。
如果需要Code @codepad
顺便说一句,它是在文档@跨越多值关系我刚刚添加了一个例子,我认为这将是有帮助的人新。
gg58donl3#
大多数情况下,一个查询只有一组可能的结果。
在处理m2m时,需要使用链接过滤器:
请考虑以下内容:
欢迎其他例子。
p1tboqfb4#
这个答案基于Django 3.1。
环境
型号
数据库表格
过滤呼叫
说明
在我开始进一步讨论之前,我必须注意到这个答案是基于使用“ManyToManyField”或反向“ForeignKey”来筛选对象的情况。
如果您使用相同的数据表或“OneToOneField”来筛选对象,则使用“多重参数筛选”或“筛选链接”之间没有差异。它们的运作方式都类似于“AND”条件筛选。
了解如何使用“多参数筛选器”和“筛选器链”的直接方法是记住在“ManyToManyField”或反向“ForeignKey”筛选器中,“多参数筛选器”是“AND”条件,而“筛选器链”是“OR”条件。
“多参数过滤器”和“过滤器链”之所以如此不同,是因为它们从不同的连接表中获取结果,并在查询语句中使用不同的条件。
“多参数筛选器”使用**“Post”.“Public_Year”= '2020'**标识公共年份
“筛选链”数据库查询使用**“T1”.“Public_Year”= '2020'**标识公共年份
但为什么不同的条件会影响结果?
我相信我们大多数来到这个页面的人,包括我=],在最初使用“多参数过滤器”和“过滤器链”时都有同样的假设。
我们认为结果应该从一个表中获取,如下面的一个表,它是正确的“多参数过滤器”。所以,如果你使用“多参数过滤器”,你会得到一个结果,如你所期望的。
但在处理“过滤链”时,Django创建了一个不同的查询语句,将上面的表更改为下面的表。此外,由于查询语句的更改,“Public Year”被标识在“T1”部分而不是“Post”部分。
但是这个奇怪的“过滤链”连接表图是从哪里来的呢?
我不是数据库Maven。下面的解释是我创建了数据库的确切结构,并使用相同的查询语句进行了测试后,到目前为止所理解的。
下图将显示这个奇怪的“过滤链”连接表图的来源。
x1c4d 1x指令集
数据库将首先通过逐个匹配“Blog”和“Post”表的行来创建连接表。
之后,数据库现在再次执行相同的匹配过程,但使用步骤1的结果表来匹配“T1”表,该表与“Post”表完全相同。
这就是这个奇怪的“过滤链”连接表图的来源。
结论
因此,有两件事使“多参数筛选器”和“筛选器链”不同。
1.“筛选器链”查询语句标识的条件来自“多参数筛选器”以外的位置。
记住如何使用它的肮脏方法是**“多参数筛选器”是一个“AND”条件,而“筛选器链”是一个“OR”**条件,而在“ManyToManyField”或反向“ForeignKey”筛选器中。
scyqe7ek5#
性能差异是巨大的,试试看吧。
Model.objects.filter(condition_a).filter(condition_b).filter(condition_c)
比之于
Model.objects.filter(condition_a, condition_b, condition_c)
正如在Effective Django ORM中提到的,
vlju58qv6#
您可以使用连接模块来查看要比较的原始sql查询。正如Yuji的解释,它们在大多数情况下是等效的,如下所示:
gstyhher7#
如果你最终在这个页面上寻找如何用多个链接过滤器动态构建一个django queryset,但是你需要过滤器是
AND
类型而不是OR
,考虑使用Q对象。举个例子:
9jyewag08#
如果需要a和B,则
如果需要A以及B,则
正式文件:https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships
相关帖子:Chaining multiple filter() in Django, is this a bug?
tcomlyy69#
当您对相关对象有请求时,这是有区别的,例如
请求
返回空集
以及点播了
返回图书同时具有“name1”和“name2”的作者
有关详细信息,请访问https://docs.djangoproject.com/en/dev/topics/db/queries/#s-spanning-multi-valued-relationships