J'ai toujours supposé que le chaînage de plusieurs appels filter () dans Django était toujours le même que leur collecte en un seul appel.
# Equivalent
Model.objects.filter(foo=1).filter(bar=2)
Model.objects.filter(foo=1,bar=2)
mais j'ai rencontré un jeu de requêtes compliqué dans mon code où ce n'est pas le cas
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')
Le SQL généré est
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 )
Le premier jeu de requêtes avec les filter()
appels enchaînés rejoint le modèle d'inventaire deux fois en créant effectivement un OU entre les deux conditions, tandis que le second jeu de requêtes ETs les deux conditions ensemble. Je m'attendais à ce que la première requête soit également ET les deux conditions. Est-ce le comportement attendu ou s'agit-il d'un bogue dans Django?
La réponse à une question connexe Y a-t-il un inconvénient à utiliser ".filter (). Filter (). Filter () ..." dans Django? semble indiquer que les deux ensembles de requêtes devraient être équivalents.