在多个参数filter和django中的链式filter之间的区别
django中有多个参数的filter和链式filter有什么区别?
正如您在生成的SQL语句中所看到的,不同之处不在于某些人可能怀疑的“或”。 这是如何放置WHERE和JOIN。
示例1(相同的连接表):从https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships
Blog.objects.filter( entry__headline__contains='Lennon', entry__pub_date__year=2008)
这将给你所有的博客有一个条目(entry__headline__contains='Lennon') AND (entry__pub_date__year=2008)
,这是你期望从这个查询。
结果:
Book with {entry.headline: 'Life of Lennon', entry.pub_date: '2008'}
示例2(链接)
Blog.objects.filter( entry__headline__contains='Lennon' ).filter( entry__pub_date__year=2008)
这将涵盖示例1的所有结果,但会产生稍微更多的结果。 因为它首先使用(entry__headline__contains='Lennon')
过滤所有博客,然后从结果filter(entry__pub_date__year=2008)
过滤。
不同的是它也会给你如下的结果:
预订
{entry.headline: '**Lennon**', entry.pub_date: 2000}, {entry.headline: 'Bill', entry.pub_date: **2008**}
一个表:但是如果查询不像Yuji和DTing的例子那样涉及到连接表。 结果是一样的。
大多数情况下,查询只有一个可能的结果集合。
链接filter的用法是在处理m2m时出现的:
考虑一下:
# 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))
其他例子欢迎。
“multiple arguments filter-query”的结果不同于“chained-filter-query”的情况如下:
在引用对象和关系的基础上select引用对象是一对多(或多对多)。
多个filter:
Referenced.filter(referencing1_a=x, referencing1_b=y) # same referencing model ^^ ^^
链式filter:
Referenced.filter(referencing1_a=x).filter(referencing1_b=y)
两个查询都能输出不同的结果:
如果引用模型Referencing1
多于一行可以引用参考模型Referencing1
中的同一行。 在Referenced
可以是这种情况:Referencing1
具有1:N(一对多)或N:M(多对多)的关系。
例:
考虑我的应用my_company
有两个模型Employee
和Dependent
。 my_company
的员工可以有更多的受抚养人(换句话说,受抚养人可以是单个雇员的儿子/女儿,而雇员可以有一个以上的儿子/女儿)。
呃,假设夫妻双方都不能在my_company
工作。 我拿了1:m的例子
所以, Employee
是被引用的模型,可以被更多的引用模型引用。 现在考虑关系状态如下:
Employee: Dependent: +------+ +------+--------+-------------+--------------+ | name | | name | E-name | school_mark | college_mark | +------+ +------+--------+-------------+--------------+ | A | | a1 | A | 79 | 81 | | B | | b1 | B | 80 | 60 | +------+ | b2 | B | 68 | 86 | +------+--------+-------------+--------------+
从属
a1
是指员工A
,依赖b1, b2
指员工B
现在我的查询是:
find所有员工在学校和学校有儿子/女儿都有区别标记(> = 75%)?
>>> Employee.objects.filter(dependent__school_mark__gte=75, ... dependent__college_mark__gte=75) [<Employee: A>]
输出是“A”,依赖于“a1”在学院和学校都有区分标记,这取决于员工“A”。 注意'B'没有被选中,因为'B'的孩子在学院和学校都有分别的标记。 关系代数:
员工⋈(school_mark> = 75且college_mark> = 75)受抚养人
其次,我需要一个查询:
find一些家属在学校和学校都有区分标记的所有员工?
>>> Employee.objects.filter( ... dependent__school_mark__gte=75 ... ).filter( ... dependent__college_mark__gte=75) [<Employee: A>, <Employee: B>]
这次'B'也是因为'B'有两个孩子(不止一个!),一个在学校有'b1'而另一个在大学'b2'有区别标记。
过滤顺序并不重要,我们也可以把上面的查询写成:
>>> Employee.objects.filter( ... dependent__college_mark__gte=75 ... ).filter( ... dependent__school_mark__gte=75) [<Employee: A>, <Employee: B>]
结果是一样的! 关系代数可以是:
(员工⋈(school_mark> = 75)受抚养人) (college_mark> = 75)受抚养人
注意如下:
dq1 = Dependent.objects.filter(college_mark__gte=75, school_mark__gte=75) dq2 = Dependent.objects.filter(college_mark__gte=75).filter(school_mark__gte=75)
输出相同的结果: [<Dependent: a1>]
我使用print qd1.query
和print qd2.query
检查由Django生成的目标SQL查询是否相同(Django 1.6)。
但是语义上两者都不同于我 。 第一个看起来像是简单的部分σ [school_mark> = 75 AND college_mark> = 75] (从属),其次是慢嵌套查询:σ [school_mark> = 75] (σ [college_mark> = 75] (Dependent))。
如果你需要Code @codepad
顺便说一句,这是在文档@ 跨越多值关系给我刚刚添加了一个例子,我认为这将有助于一个新的。
您可以使用连接模块查看要比较的原始sql查询。 正如Yuji所解释的那样,它们大部分是相同的,如下所示:
>>> from django.db import connection >>> samples1 = Unit.objects.filter(color="orange", volume=None) >>> samples2 = Unit.objects.filter(color="orange").filter(volume=None) >>> list(samples1) [] >>> list(samples2) [] >>> for q in connection.queries: ... print q['sql'] ... SELECT `samples_unit`.`id`, `samples_unit`.`color`, `samples_unit`.`volume` FROM `samples_unit` WHERE (`samples_unit`.`color` = orange AND `samples_unit`.`volume` IS NULL) SELECT `samples_unit`.`id`, `samples_unit`.`color`, `samples_unit`.`volume` FROM `samples_unit` WHERE (`samples_unit`.`color` = orange AND `samples_unit`.`volume` IS NULL) >>>
性能差异是巨大的。 试试看看。
Model.objects.filter(condition_a).filter(condition_b).filter(condition_c)
相比之下是惊人的慢
Model.objects.filter(condition_a, condition_b, condition_c)
正如“Effective Django ORM”中所提到的,
- QuerySets在内存中维护状态
- 链接触发克隆,复制该状态
- 不幸的是,QuerySets保持了很多状态
- 如果可能的话,不要链接多个filter
如果你最终在这个页面上寻找如何使用多个链接filter来dynamic构build一个Django查询集,但是你需要filter是AND
types而不是OR
,那么考虑使用Q对象 。
一个例子:
# First filter by type. filters = None if param in CARS: objects = app.models.Car.objects filters = Q(tire=param) elif param in PLANES: objects = app.models.Plane.objects filters = Q(wing=param) # Now filter by location. if location == 'France': filters = filters & Q(quay=location) elif location == 'England': filters = filters & Q(harbor=location) # Finally, generate the actual queryset queryset = objects.filter(filters)
例如,当您向相关对象发出请求时,就会有所不同
class Book(models.Model): author = models.ForeignKey(Author) name = models.ForeignKey(Region) class Author(models.Model): name = models.ForeignKey(Region)
请求
Author.objects.filter(book_name='name1',book_name='name2')
返回空集
并要求
Author.objects.filter(book_name='name1').filter(book_name='name2')
返回具有“name1”和“name2”两种书籍的作者
有关详细信息, 请参阅https://docs.djangoproject.com/en/dev/topics/db/queries/#s-spanning-multi-valued-relationships