Siempre asumí que encadenar múltiples llamadas filter () en Django era siempre lo mismo que recopilarlas en una sola llamada.
# Equivalent
Model.objects.filter(foo=1).filter(bar=2)
Model.objects.filter(foo=1,bar=2)
pero me he encontrado con un conjunto de consultas complicado en mi código donde este no es el caso
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')
El SQL generado es
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 )
El primer conjunto de consultas con las filter()
llamadas encadenadas se une al modelo de Inventario dos veces, creando un OR entre las dos condiciones, mientras que el segundo conjunto de consultas aplica un AND a las dos condiciones juntas. Esperaba que la primera consulta también Y las dos condiciones. ¿Es este el comportamiento esperado o es un error en Django?
La respuesta a una pregunta relacionada ¿Hay alguna desventaja en el uso de ".filter (). Filter (). Filter () ..." en Django? parece indicar que los dos conjuntos de consultas deberían ser equivalentes.