Django ORM – objects.filter () vs. objects.all (). Filter () – ¿cuál es el preferido?

Muy a menudo veo constructos como

MyModel.objects.all().filter(...) 

que devolverá un QuerySet del administrador predeterminado. Al principio, all() parece ser bastante redundante, porque

 MyMode.objects.filter(...) 

Ofrece el mismo resultado.

Sin embargo, esto parece ser seguro solo para el Administrador predeterminado, debido a las siguientes dos declaraciones en la documentación de Django:

Extracto del capítulo “Adición de métodos de administrador adicionales”

Un método de administrador personalizado puede devolver lo que quieras. No tiene que devolver un QuerySet.

Definición del método all() manager:

all () Devuelve una copia del QuerySet actual (o subclase QuerySet). Esto puede ser útil en situaciones en las que es posible que desee pasar un administrador de modelos o un QuerySet y realizar un filtrado adicional sobre el resultado. Después de llamar a all () en cualquier objeto, definitivamente tendrá un QuerySet para trabajar.

Esto me parece un poco como una contradicción. Por un lado, Django ofrece la libertad de permitir que un método de administrador devuelva cualquier tipo de objeto preferido y por otro lado requiere un QuerySet para el método all() . Soy consciente de que cada administrador tiene un método get_queryset que es llamado por all() . Pero, ¿quién me impide anular all() en mi administrador personalizado? Aunque estoy de acuerdo en que sería un mal diseño hacerlo.

  • Por lo que puedo ver, el método all() no garantiza devolver un QuerySet. ¿Qué devuelve exactamente MyModel.objects ? ¿Esta statement llama a all() ? o `get_queryset ()?

  • ¿Prefiere MyModel.objects.filter(...) o MyModel.objects.all().filter(...) . Y si es así, ¿por qué?

  • ¿Alguna vez se ha encontrado con administradores malintencionados que ensuciarían esos métodos de una manera no deseada?

El método all() en un administrador simplemente delega a get_queryset() , como se puede ver en el código fuente de Django :

 def all(self): return self.get_queryset() 

Así que es solo una forma de obtener QuerySet desde el Administrador. Esto puede ser útil para asegurarse de que está tratando con un QuerySet y no con un Administrador, porque MyModel.objects devuelve un Administrador.

Por ejemplo, si desea iterar sobre todos los elementos, no puede hacer esto:

 for item in MyModel.objects: # do something with item 

Porque no puedes iterar sobre un Manager. Sin embargo, all() devuelve el QuerySet, puede iterar sobre un QuerySet:

 for item in MyModel.objects.all(): # do something with item 

En general, nunca debe sobrescribir all() . Puede sobrescribir get_queryset() pero este método debe devolver un QuerySet.

Si usara un método de filtro como filter() o exclude() , ya tendría el QuerySet, porque estos métodos están vinculados al QuerySet . Así que no tienes que hacer algo como all().filter() .

  1. MyModel.objects devuelve la instancia del administrador. all() devuelve get_query_set() . Creo que todo está ahí cuando necesitas todos los objetos.
  2. Prefiero MyModel.objects.filter() porque el otro es solo una llamada de método más, y no necesito todos los objetos si hago un filtro 🙂
  3. Depende del propósito. Pero si anulan un método base del administrador, devuelven el mismo formato de resultado (por ejemplo, un QuerySet)

Mymodel.objects.filter(username='abcd') dará una lista del registro de coincidencias Mymodel.objects.get(pk='abcd') devolverá un registro único con coincidencia en el valor de la clave principal