Recherche de queryset vide dans Django
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 de vérifier cela, mais j'aimerais savoir comment un utilisateur Django expérimenté le ferait. La plupart des exemples dans les documents ignorent simplement le cas où rien n'a été trouvé...
7 réponses
Depuis la version 1.2, Django a QuerySet.existe() la méthode qui est le plus efficace:
if orgs.exists():
# Do this...
else:
# Do that...
Mais si vous allez évaluer QuerySet de toute façon, il est préférable d'utiliser:
if orgs:
...
Pour plus d'informations lire QuerySet.exists () documentation .
Si vous avez un grand nombre d'objets, cela peut (parfois) être beaucoup plus rapide:
try:
orgs[0]
# If you get here, it exists...
except IndexError:
# Doesn't exist!
Sur un projet sur lequel je travaille avec une énorme base de données, not orgs
est 400 + ms et orgs.count()
est 250ms. dans Mes cas d'utilisation les plus courants (ceux où il y a des résultats), cette technique descend souvent à moins de 20ms. (un cas que j'ai trouvé, c'était 6.)
Pourrait être beaucoup plus long, bien sûr, en fonction de la distance que la base de données doit chercher pour trouver un résultat. Ou encore plus vite, s'il en trouve un rapidement; YMMV.
EDIT: Ce sera souvent être plus lent que orgs.count()
si le résultat n'est pas trouvé, en particulier si la condition que vous êtes le filtrage est une rare; en conséquence, il est particulièrement utile dans les fonctions d'affichage où vous devez assurez-vous que le point de vue existe, ni de jeter Http404. (Où, on l'espère, les gens demandent des URL qui existent le plus souvent.)
Pour vérifier le vide d'un queryset:
if orgs.exists():
# Do something
Ou vous pouvez vérifier le premier élément d'un queryset, s'il n'existe pas, il retournera None
:
if orgs.first():
# Do something
Je ne suis pas d'accord avec le prédicat
if not orgs:
, Il devrait être
if not orgs.count():
J'avais le même problème avec un jeu de résultats assez important (~150k résultats). L'opérateur n'est pas surchargé dans QuerySet, de sorte que le résultat est réellement décompressé en tant que liste avant la vérification. Dans mon cas, le temps d'exécution a diminué de trois ordres.
Le moyen le plus efficace (avant django 1.2) est le suivant:
if orgs.count() == 0:
# no results
else:
# alrigh! let's continue...
Vous pouvez utiliser len
ou last()
if not len(orgs):
# if queryset is empty do something
if not orgs.last():
# if queryset is empty do something