Ich habe immer angenommen, dass das Verketten mehrerer filter () -Aufrufe in Django immer dasselbe ist wie das Sammeln in einem einzigen Aufruf.
# Equivalent
Model.objects.filter(foo=1).filter(bar=2)
Model.objects.filter(foo=1,bar=2)
Ich bin jedoch auf einen komplizierten Abfragesatz in meinem Code gestoßen, bei dem dies nicht der Fall ist
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')
Das generierte SQL ist
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 )
Das erste Abfrageset mit den verketteten filter()
Aufrufen verbindet das Inventarmodell zweimal und erstellt effektiv ein ODER zwischen den beiden Bedingungen, während das zweite Abfrageset die beiden Bedingungen UND-verknüpft. Ich hatte erwartet, dass die erste Abfrage auch UND die beiden Bedingungen würde. Ist dies das erwartete Verhalten oder ist dies ein Fehler in Django?
Die Antwort auf eine verwandte Frage Gibt es einen Nachteil bei der Verwendung von ".filter (). Filter (). Filter () ..." in Django? scheint darauf hinzudeuten, dass die beiden Abfragesätze gleichwertig sein sollten.