280

What is the recommended idiom for checking whether a query returned any results?
Example:

orgs = Organisation.objects.filter(name__iexact = 'Fjuk inc')
# If any results
    # Do this with the results without querying again.
# Else, do something else...

I suppose there are several different ways of checking this, but I'd like to know how an experienced Django user would do it. Most examples in the docs just ignore the case where nothing was found...

Niklas
  • 5,736
  • 7
  • 35
  • 42

7 Answers7

326
if not orgs:
    # The Queryset is empty ...
else:
    # The Queryset has results ...
chris Frisina
  • 19,086
  • 22
  • 87
  • 167
Adam
  • 7,067
  • 2
  • 27
  • 24
  • 8
    This seems to be preferred in the documentation too, for instance: https://docs.djangoproject.com/en/1.8/topics/http/shortcuts/#id7 – Wtower May 22 '15 at 09:02
  • 1
    @Wtower The code you refer to has for contract to raise 404 if the filtering expression does not hit any records or to produce a `list` of the result if there are records. The code there will hit the database just once. If they used `exist()` or `count()` to first check whether there are going to be records returned, they'd be hitting the database twice (once to check, once to get the records). This is a specific situation. It does not entail that in the *general case*, the preferred method to know whether a query will return records is to use do `if queryset:...` – Louis Nov 03 '15 at 16:26
  • 1
    @Louis the code I refer to is only an example that it contains a line `if not my_objects:` to demonstrate that this is how they do it in the docs. All else is utterly irrelevant so I do not get your point. They could as well make a thousand queries and it would still be totally irrelevant as this is not the point of this answer, with which I make clear that I agree. – Wtower Nov 04 '15 at 08:47
  • 1
    @Wtower That is ***just an explanation*** of how `get_object_or_404` works, ***not*** a preferred way of checking whether any elements exists in a queryset. Doing list() on a queryset will fetch every objects on a queryset, which would be worse than querying twice if there are a lot of rows returned. – minmaxavg Dec 03 '15 at 15:10
  • 5
    For a more detailed answer look at @leonid-shvechikov 's answer below: using `.exists()` is more efficient if the qs is not going to be evaluated. – gdvalderrama May 25 '18 at 10:06
  • Large QS will be evaluated in memory cause overflow ! – Sion C May 21 '21 at 17:36
270

Since version 1.2, Django has QuerySet.exists() method which is the most efficient:

if orgs.exists():
    # Do this...
else:
    # Do that...

But if you are going to evaluate QuerySet anyway it's better to use:

if orgs:
   ...

For more information read QuerySet.exists() documentation.

Leonid Shvechikov
  • 3,927
  • 2
  • 17
  • 14
20

To check the emptiness of a queryset:

if orgs.exists():
    # Do something

or you can check for a the first item in a queryset, if it doesn't exist it will return None:

if orgs.first():
    # Do something
Tuss4
  • 363
  • 2
  • 7
  • 11
    `if orgs.exists()` was covered by an [answer](http://stackoverflow.com/a/2373793/1906307) that was provided about 5 years before this one. The only thing this answer brings to the table which is *perhaps* new is `if orgs.first()`. (Even this is debatable: is it substantially different from doing the `orgs[0]` [suggested](http://stackoverflow.com/a/2098092/1906307) about 5 years ago too?) You ought to develop that part of the answer: when would one want to do this **instead of** the other solutions proposed earlier? – Louis Nov 03 '15 at 16:33
18

If you have a huge number of objects, this can (at times) be much faster:

try:
    orgs[0]
    # If you get here, it exists...
except IndexError:
    # Doesn't exist!

On a project I'm working on with a huge database, not orgs is 400+ ms and orgs.count() is 250ms. In my most common use cases (those where there are results), this technique often gets that down to under 20ms. (One case I found, it was 6.)

Could be much longer, of course, depending on how far the database has to look to find a result. Or even faster, if it finds one quickly; YMMV.

EDIT: This will often be slower than orgs.count() if the result isn't found, particularly if the condition you're filtering on is a rare one; as a result, it's particularly useful in view functions where you need to make sure the view exists or throw Http404. (Where, one would hope, people are asking for URLs that exist more often than not.)

Adam Playford
  • 286
  • 2
  • 6
13

The most efficient way (before django 1.2) is this:

if orgs.count() == 0:
    # no results
else:
    # alrigh! let's continue...
dzida
  • 8,854
  • 2
  • 36
  • 57
Bartosz
  • 6,055
  • 3
  • 27
  • 17
  • 6
    .exists() seems to be even more efficient – dzida Mar 28 '12 at 07:12
  • 8
    Except that .exists() was added few months after my comment, and Django 1.2 (which incorporated that API) was released ~8 months later. But thanks for down-voting and not bothering to check the facts. – Bartosz Sep 12 '12 at 20:26
  • 5
    Sorry, I added small edit to your answer to make it more accurate and voted positively. – dzida Sep 13 '12 at 10:10
6

I disagree with the predicate

if not orgs:

It should be

if not orgs.count():

I was having the same issue with a fairly large result set (~150k results). The operator is not overloaded in QuerySet, so the result is actually unpacked as a list before the check is made. In my case execution time went down by three orders.

hedleyroos
  • 320
  • 3
  • 9
  • 6
    _\_nonzero_\_ is already overloaded in QuerySet. If the result is not cached (it never is on first use of the queryset) the behaviour of _\_nonzero_\_ is to iterate over all elements in queryset. This is very bad if the set is large. – hedleyroos Jul 30 '11 at 15:45
-2

You could also use this:

if(not(orgs)): #if orgs is empty else: #if orgs is not empty

  • 2
    Your answer is no different to an answer posted ten years earlier, the only difference being two pairs of unnecessary brackets. – rioted Apr 22 '22 at 21:24