一尘不染

在Django中链接多个filter(),这是一个错误吗?

django

我一直认为在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()调用的第一个查询集两次连接库存模型,从而有效地在两个条件之间创建了“或”,而第二个查询集将这两个条件与在一起。我期望第一个查询也将同时满足这两个条件。这是预期的行为,还是Django中的错误?


阅读 601

收藏
2020-03-27

共1个答案

一尘不染

我的理解是,它们在设计上有细微的差别(并且我当然愿意接受更正):filter(A, B)将首先根据A进行过滤,然后根据B进行子过滤,同时filter(A).filter(B)将返回与A’匹配的行,并且可能会匹配B的行。

2020-03-27