跨越 multi-valued 关系
Spanning multi-valued relationships
我阅读了 django 文档,发现了一些令人困惑的地方!
https://docs.djangoproject.com/en/3.2/topics/db/queries/#spanning-multi-valued-relationships.
据说“当您根据 ManyToManyField 或反向外键过滤 object 时,您可能会对两种不同类型的过滤器感兴趣
“对于 select 所有包含标题中同时包含“Lennon”条目且发表于 2008 年的博客(满足这两个条件的同一条目),我们会写:”
Blog.objects.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008)
“对于 select 所有标题中包含“Lennon”的条目以及 2008 年发布的条目的博客,我们会写:“
Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)
“假设只有一个博客的条目包含“Lennon”和 2008 年的条目,但是 2008 年的 none 条目包含“Lennon”。第一个查询不会 return 任何博客,但第二个查询会 return 那个博客
因此,通过阅读本指南,我脑海中产生了多个问题:
1- 这两种过滤有什么区别?我所知道的是,它们都必须 return 博客在标题中包含 'Lennon' 并且发表于 2008 年。我找不到重点。
2- 文档说此规则仅适用于 ManyToManyField 或反向外键。问题是,为什么?
What is the difference between these two types of filtering?
假设您有一个包含两个(或更多)条目的 Blog
。其中一个条目的标题是一些包含单词 'Lennon'
但 不是 写于 2008 年的文本,此外该博客还有一个条目 without 标题中的单词 'Lennon'
,但写于 2008 年。
带有 .filter(entry__headline__contains='Lennon', entry__pub_date__year=2008)
的第一个查询查找标题中包含 'Lennon'
的条目 和 相同的条目应该写在 2008 年。对于我们在第一段中定义的样本数据,这将意味着此 Blog
未被选择 而不是 ,因为这两个条件适用于 same条目。
另一方面,如果您将其写为 .filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)
,Django 将生成 两个 LEFT OUTER JOIN
,这意味着它会查找一个博客,其中如果条目的标题包含 Lennon
,并且一个条目(可以是 不同的 或相同的条目)是在 2008 年写的。这将检索 Blog
定义在第一段。
The Document says this rule is just for ManyToManyField
or a reverse ForeignKey
. The question is, Why?
因为反向 ForeignKey
是 one-to-many 关系,而 ManyToManyField
跨越 many-to-many 关系。 …-to-many
在这里很重要。如果那将是 …-to-one
,则根本不可能创建包含两个或更多条目的 Blog
:如果 Blog
具有 ForeignKey
到 Entry
model,那么就意味着博客只能有一个条目,不能有多个条目。由于这因此将条目数限制为一个,因此不可能有两个或更多条目,因此过滤将不会区分这两种情况。
我阅读了 django 文档,发现了一些令人困惑的地方! https://docs.djangoproject.com/en/3.2/topics/db/queries/#spanning-multi-valued-relationships.
据说“当您根据 ManyToManyField 或反向外键过滤 object 时,您可能会对两种不同类型的过滤器感兴趣
“对于 select 所有包含标题中同时包含“Lennon”条目且发表于 2008 年的博客(满足这两个条件的同一条目),我们会写:”
Blog.objects.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008)
“对于 select 所有标题中包含“Lennon”的条目以及 2008 年发布的条目的博客,我们会写:“
Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)
“假设只有一个博客的条目包含“Lennon”和 2008 年的条目,但是 2008 年的 none 条目包含“Lennon”。第一个查询不会 return 任何博客,但第二个查询会 return 那个博客
因此,通过阅读本指南,我脑海中产生了多个问题:
1- 这两种过滤有什么区别?我所知道的是,它们都必须 return 博客在标题中包含 'Lennon' 并且发表于 2008 年。我找不到重点。
2- 文档说此规则仅适用于 ManyToManyField 或反向外键。问题是,为什么?
What is the difference between these two types of filtering?
假设您有一个包含两个(或更多)条目的 Blog
。其中一个条目的标题是一些包含单词 'Lennon'
但 不是 写于 2008 年的文本,此外该博客还有一个条目 without 标题中的单词 'Lennon'
,但写于 2008 年。
带有 .filter(entry__headline__contains='Lennon', entry__pub_date__year=2008)
的第一个查询查找标题中包含 'Lennon'
的条目 和 相同的条目应该写在 2008 年。对于我们在第一段中定义的样本数据,这将意味着此 Blog
未被选择 而不是 ,因为这两个条件适用于 same条目。
另一方面,如果您将其写为 .filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)
,Django 将生成 两个 LEFT OUTER JOIN
,这意味着它会查找一个博客,其中如果条目的标题包含 Lennon
,并且一个条目(可以是 不同的 或相同的条目)是在 2008 年写的。这将检索 Blog
定义在第一段。
The Document says this rule is just for
ManyToManyField
or a reverseForeignKey
. The question is, Why?
因为反向 ForeignKey
是 one-to-many 关系,而 ManyToManyField
跨越 many-to-many 关系。 …-to-many
在这里很重要。如果那将是 …-to-one
,则根本不可能创建包含两个或更多条目的 Blog
:如果 Blog
具有 ForeignKey
到 Entry
model,那么就意味着博客只能有一个条目,不能有多个条目。由于这因此将条目数限制为一个,因此不可能有两个或更多条目,因此过滤将不会区分这两种情况。