Quel est l'idiome recommandé pour vérifier si une requête a renvoyé des résultats?
Exemple:
orgs = Organisation.objects.filter(name__iexact = 'Fjuk inc')
# If any results
# Do this with the results without querying again.
# Else, do something else...
Je suppose qu'il existe plusieurs façons différentes de vérifier cela, mais j'aimerais savoir comment un utilisateur Django expérimenté le ferait. La plupart des exemples dans la documentation ignorent simplement le cas où rien n'a été trouvé ...
django
django-queryset
Niklas
la source
la source
list
résultat s'il existe des enregistrements. Le code ne frappera la base de données qu'une seule fois. S'ils utilisaientexist()
oucount()
pour vérifier d'abord s'il y aura des enregistrements retournés, ils frapperaient la base de données deux fois (une fois pour vérifier, une fois pour obtenir les enregistrements). C'est une situation particulière. Cela n'implique pas que dans le cas général , la méthode préférée pour savoir si une requête renverra des enregistrements est d'utiliser doif queryset:...
if not my_objects:
pour démontrer que c'est ainsi qu'ils le font dans la documentation. Tout le reste est totalement hors de propos, je ne comprends donc pas votre point de vue. Ils pourraient tout aussi bien faire mille requêtes et ce serait encore totalement hors de propos car ce n'est pas le but de cette réponse, avec laquelle je précise que je suis d'accord.get_object_or_404
fonctionne, pas une manière préférée de vérifier si des éléments existent dans un jeu de requêtes. Faire list () sur un ensemble de requêtes récupérera tous les objets d'un ensemble de requêtes, ce qui serait pire que d'interroger deux fois s'il y a beaucoup de lignes renvoyées..exists()
est plus efficace si le qs ne va pas être évalué.Depuis la version 1.2, Django a QuerySet. existe () méthode qui est la plus efficace:
Mais si vous envisagez d'évaluer QuerySet de toute façon, il est préférable d'utiliser:
Pour plus d'informations, lisez la documentation QuerySet.exists () .
la source
.get
ne renvoie pas de jeu de requête. Il renvoie un objet. Alors google pour çaSi vous avez un grand nombre d'objets, cela peut (parfois) être beaucoup plus rapide:
Sur un projet sur lequel je travaille avec une énorme base de données,
not orgs
c'est plus de 400 ms etorgs.count()
250 ms . Dans mes cas d'utilisation les plus courants (ceux où il y a des résultats), cette technique ramène souvent cela à moins de 20 ms. (Un cas que j'ai trouvé, c'était 6.)Cela pourrait être beaucoup plus long, bien sûr, en fonction de la distance à parcourir dans la base de données pour trouver un résultat. Ou encore plus vite, s'il en trouve un rapidement; YMMV.
EDIT: Cela sera souvent plus lent que
orgs.count()
si le résultat n'est pas trouvé, en particulier si la condition sur laquelle vous filtrez est rare; par conséquent, il est particulièrement utile dans les fonctions de vue où vous devez vous assurer que la vue existe ou lancer Http404. (Là où, on pourrait l'espérer, les gens demandent des URL qui existent le plus souvent.)la source
Pour vérifier la vacuité d'un jeu de requêtes:
ou vous pouvez rechercher le premier élément d'un jeu de requêtes, s'il n'existe pas, il retournera
None
:la source
if orgs.exists()
a fait l'objet d'une réponse apportée environ 5 ans avant celle-ci. La seule chose que cette réponse apporte à la table qui est peut - être nouvelle estif orgs.first()
. (Même cela est discutable: est-ce substantiellement différent de faire ce qui a étéorgs[0]
suggéré il y a environ 5 ans?) Vous devriez développer cette partie de la réponse: quand voudrait-on faire cela au lieu des autres solutions proposées plus tôt?Le moyen le plus efficace (avant django 1.2) est le suivant:
la source
Je ne suis pas d'accord avec le prédicat
Ça devrait être
J'avais le même problème avec un ensemble de résultats assez volumineux (~ 150k résultats). L'opérateur n'est pas surchargé dans QuerySet, donc le résultat est en fait décompressé sous forme de liste avant que la vérification ne soit effectuée. Dans mon cas, le temps d'exécution a diminué de trois ordres.
la source
Vous pouvez également utiliser ceci:
if(not(orgs)): #if orgs is empty else: #if orgs is not empty
la source