Django跨多值关系两种filter过滤逻辑差异及适用范围疑问
两种过滤写法的逻辑差异
两种写法的核心区别是关联条件是否作用在同一个关联对象实例上,底层是生成的SQL JOIN逻辑不同:
- 单个
filter传入多个跨多值关系的条件:Django仅会对关联表做1次JOIN,所有条件都会作用到同一个关联的entry行上。等价于要求博客下存在至少1个entry同时满足「标题含Lennon」+「2008年发布」两个条件。
对应文档举的例子里,该博客的2008年entry都不含Lennon,含Lennon的entry不是2008年发布的,不存在同时满足两个条件的entry,所以查询无结果。
对应代码:Blog.objects.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008) - 链式调用多个
filter:每个涉及多值关系的filter都会单独做1次JOIN,不同filter的条件作用到不同的关联entry行上。等价于要求博客下至少存在1个entry满足「标题含Lennon」,同时还至少存在另1个entry(可以和前一个不是同一个)满足「2008年发布」。
对应文档举的例子里,博客同时有符合两个条件的不同entry,所以会返回该博客。
对应代码:Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)
规则仅适用于多值关系的原因
这个差异的本质是「多值关系允许一个主对象关联多个从对象」,所以才会出现“条件作用在同一个从对象还是不同从对象”的区别。
而正向ForeignKey、OneToOneField都属于单值关系:一个主对象只能关联唯一的一个从对象,不管你把条件写在同一个filter里还是拆成链式filter,所有条件都只能作用到那唯一的关联对象上,不存在两种逻辑的差异,因此该规则不需要适用于单值关系场景。
内容的提问来源于stack exchange,提问作者Adel Abdoli
相关产品推荐
相关产品推荐

