Zawsze zakładałem, że łączenie w łańcuch wielu wywołań filter () w Django jest zawsze tym samym, co zbieranie ich w jednym wywołaniu.
# Equivalent
Model.objects.filter(foo=1).filter(bar=2)
Model.objects.filter(foo=1,bar=2)
ale natknąłem się na skomplikowany zestaw zapytań w moim kodzie, gdzie tak nie jest
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')
Wygenerowany kod SQL to
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 )
Pierwszy zestaw zapytań z połączonymi filter()
wywołaniami dwukrotnie łączy się z modelem Inventory, tworząc OR między dwoma warunkami, podczas gdy drugi zestaw zapytań ORAZ te dwa warunki razem. Spodziewałem się, że pierwsze zapytanie będzie również ORAZ dwoma warunkami. Czy jest to oczekiwane zachowanie, czy jest to błąd w Django?
Odpowiedź na pokrewne pytanie Czy używanie funkcji „.filter (). Filter (). Filter () ...” w Django ma wady? wydaje się wskazywać, że dwa zestawy zapytań powinny być równoważne.