我阅读了django文档,发现了一些令人困惑的东西!https://docs.djangoproject.com/en/3.2/topics/db/queries/#spanning-multi-valued-relationships。
据说,“当您基于ManyToManyField或反向ForeignKey筛选对象时,您可能会对两种不同类型的筛选器感兴趣”。
为了选择所有在标题中包含两个“Lennon”的条目并于2008年发布的博客(满足这两种条件的相同条目),我们将这样写:
Blog.objects.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008)为了选择所有在标题中包含“列侬”条目的博客,以及2008年发表的文章,我们会写:
Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)假设只有一个博客同时包含“Lennon”和2008年的条目,但2008年的条目中没有一个包含“Lennon”。第一个查询不会返回任何博客,但是第二个查询将返回该博客。
因此,通过阅读本指南,我的脑海中产生了多个问题:
这两种过滤的区别是什么?我所知道的是,他们都必须返回的博客,其中包含两个‘列侬’的标题,并于2008年出版。我找不出重点。
文档中说,这条规则只适用于ManyToManyField或反向ForeignKey。问题是,为什么?
发布于 2021-09-19 19:23:26
这两种过滤的区别是什么?
假设您有一个包含两个(或更多)条目的Blog。其中一个条目的标题是一些包含单词'Lennon'的文本,但不是在2008年编写的,此外,博客的标题中没有'Lennon'这个词,而是在2008年写的。
第一个带有.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008)的查询查找标题中包含'Lennon'的条目,该条目应该在2008年编写。对于我们在第一段中定义的样本数据,这意味着没有选择这个Blog,因为这两个条件适用于同一个条目。
另一方面,如果您将其写为.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008),Django将生成两个LEFT OUTER JOIN,这意味着它将查找一个博客,其中一个条目包含一个包含Lennon的标题,一个条目(可以是不同的条目,也可以是相同的条目)已经在2008年编写。因此,这将检索第一段中定义的Blog。
文档说,这条规则只适用于
ManyToManyField或反向ForeignKey。问题是,为什么?
因为反向ForeignKey是一对多的关系,而ManyToManyField是多到多的关系.…-to-many在这里很重要。如果这是一个…-to-one,那么就不可能用两个或多个条目创建一个Blog:如果一个Blog有一个ForeignKey到一个Entry模型,那么这意味着博客只能有一个条目,而不是多个条目。由于这样限制了条目的数目,所以不可能有两个或多个条目,因此过滤不会区分这两种情况。
https://stackoverflow.com/questions/69246373
复制相似问题