django中带有多个参数的过滤器和链式过滤器有什么区别?
Answers:
正如您在生成的SQL语句中看到的那样,差异不是某些人可能怀疑的“ OR”。这是WHERE和JOIN放置的方式。
Example1(相同的联接表):来自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)
这将为您提供所有两个条目都具有一个条目的Blog (entry__headline__contains='Lennon') AND (entry__pub_date__year=2008)
,这是您从该查询中获得的期望。
结果:
Blog 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')
结果过滤器过滤所有博客,然后使用结果过滤器过滤所有博客(entry__pub_date__year=2008)
。
不同之处在于它还会为您提供以下结果:
具有多个条目的单个Blog
{entry.headline: '**Lennon**', entry.pub_date: 2000},
{entry.headline: 'Bill', entry.pub_date: **2008**}
评估第一个过滤器时,由于包含第一个条目,因此将其包括在内(即使该条目的其他条目不匹配也是如此)。当评估第二个过滤器时,由于有第二个条目,所以将这本书包括在内。
一个表:但是,如果查询不涉及联接表,例如Yuji和DTing中的示例。结果是一样的。
(entry__headline__contains='Lennon')
然后从结果过滤器中过滤(entry__pub_date__year=2008)
”“如果“然后从结果中”是准确的,为什么要在其中包含一些内容entry.headline == 'Bill'
。 。不会entry__headline__contains='Lennon'
筛选出Bill
实例吗?
“多个参数filter-query”的结果与“ chained-filter-query”的结果不同的情况如下:
基于引用对象和关系来选择引用对象是一对多(或多对多)的。
多个过滤器:
Referenced.filter(referencing1_a=x, referencing1_b=y) # same referencing model ^^ ^^
链接的过滤器:
Referenced.filter(referencing1_a=x).filter(referencing1_b=y)
两种查询都可以输出不同的结果:
如果引用模型Referencing1
中的一行多,则可以引用referenced-model中的同一行Referenced
。在以下情况中可能是这种情况Referenced
:Referencing1
具有1:N(一对多)或N:M(多对多)关系。
例:
考虑我的申请my_company
有两种型号Employee
,并Dependent
。的雇员my_company
可以有多个受抚养人(换句话说,一个受抚养人可以是一个雇员的儿子/女儿,而一个雇员可以有多个儿子/女儿)。
恩,假设丈夫和妻子都不能在家里工作my_company
。我以1:m为例
因此,Employee
被引用的模型可以比被Dependent
引用的模型更多。现在考虑如下的关系状态:
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
。
现在我的查询是:
是否找到所有拥有儿子/女儿在大学和学校都有显着标记(例如> = 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)相关
在第二种情况下,我需要一个查询:
查找所有在大学和学校中其受抚养人具有显着标记的雇员吗?
>>> 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>]
我检查了Django使用生成的目标SQL查询print qd1.query
,print qd2.query
两者都相同(Django 1.6)。
但是从语义上来说我都不一样。第一个看起来像简单的部分σ [school_mark> = 75 AND college_mark> = 75](从属),第二个看起来像慢嵌套查询:σ [school_mark> = 75](σ [college_mark> = 75](从属))。
如果需要Code @codepad
顺便说一句,它在文档中给出@跨越多值关系我刚刚添加了一个示例,我认为这对新人会有所帮助。
在大多数情况下,查询只有一组可能的结果。
处理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))
欢迎其他示例。
性能差异巨大。试试看。
Model.objects.filter(condition_a).filter(condition_b).filter(condition_c)
相比于
Model.objects.filter(condition_a, condition_b, condition_c)
- QuerySet维护内存中的状态
- 链接触发克隆,复制该状态
- 不幸的是,QuerySet保持很多状态
- 如果可能,请勿链接多个过滤器
您可以使用连接模块查看要比较的原始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)
>>>
如果您最终在此页面上寻找如何动态构建带有多个链接过滤器的django查询集,但是您需要过滤器的AND
类型不是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)
如果需要a和b
and_query_set = Model.objects.filter(a=a, b=b)
如果需要a和b,则
chaied_query_set = Model.objects.filter(a=a).filter(b=b)
官方文件:https : //docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships
对相关对象的请求有所不同,例如
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
Author.objects.filter(book_name='name1',book_name='name2')
甚至不是有效的python,而是SyntaxError: keyword argument repeated