web-dev-qa-db-fra.com

Django ORM - objects.filter () vs. objects.all (). Filter () - lequel est préféré?

Très souvent, je vois des constructions comme

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

qui renverra un QuerySet du gestionnaire par défaut. Au début, all() semble être assez redondant, car

MyMode.objects.filter(...)

fournit le même résultat.

Cependant, cela semble être sûr pour le gestionnaire par défaut uniquement, en raison des deux instructions suivantes dans la documentation Django:

Extrait du chapitre "Ajouter des méthodes de gestion supplémentaires"

Une méthode Manager personnalisée peut renvoyer tout ce que vous voulez. Il n'a pas besoin de renvoyer un QuerySet.

Définition de la méthode gestionnaire all():

all () Renvoie une copie du QuerySet actuel (ou de la sous-classe QuerySet). Cela peut être utile dans les situations où vous souhaiterez peut-être passer un gestionnaire de modèles ou un QuerySet et filtrer davantage le résultat. Après avoir appelé all () sur l'un ou l'autre objet, vous aurez certainement un QuerySet avec lequel travailler.

Cela me semble un peu comme une contradiction. D'une part Django offre la liberté de laisser une méthode gestionnaire retourner n'importe quel type d'objet préféré et d'autre part, elle nécessite un QuerySet pour la méthode all(). Je suis sachant que chaque gestionnaire a une méthode get_queryset qui est appelée par all(). Mais qui m'empêche de remplacer all() dans mon gestionnaire personnalisé? Bien que je convienne que ce serait mauvais conception pour le faire.

  • Pour autant que je puisse voir, la méthode all() ne garantit pas de retourner un QuerySet. Que renvoie exactement MyModel.objects? Cette instruction appelle-t-elle all()? ou `get_queryset ()?

  • Préférez-vous MyModel.objects.filter(...) ou MyModel.objects.all().filter(...). Et si oui, pourquoi?

  • Avez-vous déjà rencontré des gestionnaires loufoques qui joueraient avec ces méthodes de manière indésirable?

37
Dr.Elch

La méthode all() sur un gestionnaire délègue simplement à get_queryset(), comme vous pouvez le voir dans le code source Django :

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

C'est donc juste un moyen d'obtenir le QuerySet du Manager. Cela peut être pratique pour garantir que vous avez affaire à un QuerySet et non à un Manager, car MyModel.objects Renvoie un Manager.

Par exemple, si vous souhaitez parcourir tous les éléments, vous ne pouvez pas faire ceci:

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

Parce que vous ne pouvez pas parcourir un gestionnaire. Cependant, all() renvoie le QuerySet, vous pouvez itérer sur un QuerySet:

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

En règle générale, vous ne devez jamais écraser all(). Vous pouvez remplacer get_queryset() mais cette méthode doit retourner un QuerySet.

Si vous utilisiez une méthode de filtrage comme filter() ou exclude(), vous auriez déjà le QuerySet, car ces méthodes sont mandatées par le QuerySet . Vous n'avez donc pas à faire quelque chose comme all().filter().

50
gitaarik
  1. MyModel.objects Renvoie l'instance de gestionnaire. all() retourne get_query_set(). Je pense que tout est là pour quand vous avez besoin de tous les objets.
  2. Je préfère MyModel.objects.filter() car l'autre n'est qu'un appel de méthode supplémentaire, et je n'ai pas besoin de tous les objets si je filtre :)
  3. Cela dépend du but. Mais s'ils remplacent une méthode de base du gestionnaire, ils renvoient le même format de résultat (par exemple, un QuerySet)
3

Mymodel.objects.filter(username='abcd') donnera la liste des enregistrements de correspondance Mymodel.objects.get(pk='abcd') renverra un enregistrement unique avec correspondance sur la valeur de la clé primaire

0
aarif faridi