我一直认为在Django中链接多个filter()调用与在单个调用中收集它们是一样的.

# Equivalent
Model.objects.filter(foo=1).filter(bar=2)
Model.objects.filter(foo=1,bar=2)

但是我在代码中遇到了一个复杂的查询集,而事实并非如此

class Inventory(models.Model):
    book = models.ForeignKey(Book)

class Profile(models.Model):
    user = models.OneToOneField(auth.models.User)
    vacation = models.BooleanField()
    country = models.CharField(max_length=30)

# Not Equivalent!
Book.objects.filter(inventory__user__profile__vacation=False).filter(inventory__user__profile__country='BR')
Book.objects.filter(inventory__user__profile__vacation=False, inventory__user__profile__country='BR')

生成的SQL为

SELECT "library_book"."id", "library_book"."asin", "library_book"."added", "library_book"."updated" FROM "library_book" INNER JOIN "library_inventory" ON ("library_book"."id" = "library_inventory"."book_id") INNER JOIN "auth_user" ON ("library_inventory"."user_id" = "auth_user"."id") INNER JOIN "library_profile" ON ("auth_user"."id" = "library_profile"."user_id") INNER JOIN "library_inventory" T5 ON ("library_book"."id" = T5."book_id") INNER JOIN "auth_user" T6 ON (T5."user_id" = T6."id") INNER JOIN "library_profile" T7 ON (T6."id" = T7."user_id") WHERE ("library_profile"."vacation" = False  AND T7."country" = BR )
SELECT "library_book"."id", "library_book"."asin", "library_book"."added", "library_book"."updated" FROM "library_book" INNER JOIN "library_inventory" ON ("library_book"."id" = "library_inventory"."book_id") INNER JOIN "auth_user" ON ("library_inventory"."user_id" = "auth_user"."id") INNER JOIN "library_profile" ON ("auth_user"."id" = "library_profile"."user_id") WHERE ("library_profile"."vacation" = False  AND "library_profile"."country" = BR )

具有链接的filter()调用的第一个查询集两次加入库存模型,有效地在两个条件之间创建OR,而第二个查询集与这两个条件进行AND运算.我原以为第一个查询也会对这两个条件执行AND操作.这是预期行为还是Django中的错误?

对相关问题Is there a downside to using ".filter().filter().filter()..." in Django?的回答似乎表明这两个查询集应该是等价的.

推荐答案

我理解它的方式是,它们在设计上略有不同(我当然愿意更正):filter(A, B)%将首先根据A进行过滤,然后根据B进行子过滤,而filter(A).filter(B)%将返回与A匹配的行‘和’与B匹配的潜在不同行‘.

看看下面的例子:

https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships

尤其:

单个过滤()调用中的所有内容都同时应用于符合所有这些要求的过滤输出项目.连续的过滤()调用进一步限制了对象集

...

在第二个示例中(过滤器(A).过滤器(B)),第一个过滤器将查询集限制为(A).第二个过滤器将博客集进一步限制为那些同样是(B)的博客.第二个过滤器 Select 的条目可能与第一个过滤器中的条目相同,也可能不同`

Django相关问答推荐

使用序列化器获取Django ORM auth_user. id数据

我找不到为什么我的DRF登录测试没有按预期工作

如何将Django项目连接到容器化的PostgreSQL数据库?

如何在Django REST框架中管理序列化程序?

try 在 django 中发送验证邮箱,出现错误

测试 - 两个类共享相同的登录代码,但它只能在一个类中工作

Django中用于外键的嵌套循环

为什么在 Docker 映像中运行我的 Django 应用程序后下载属性不再起作用?

在Django Rest Framework中按模型属性排序时如何避免重新计算?

使用 Django 一次更新多条记录

Playframework 和 Django

Django InlineModelAdmin:部分显示内联模型并链接到完整模型

在 Django CharFields 中自动截断 max_length 字段

断开模型的信号并在 django 中重新连接

如何使用基于类的视图处理表单(通过 get 或 post)?

Django 模板和变量属性

更改 Django ModelChoiceField 以显示用户的全名而不是用户名

Django:如何从模板中识别调用视图?

通过 django 分页仅显示部分页码

Django 多动态数据库