Question

I'm writing tests for a django application and I want to check if an object has been saved to the database. Which is the most efficient/correct way to do it?

User.objects.filter(username=testusername).exists()

or

try:
    User.objects.get(username=testusername)
except User.DoesNotExist:
Was it helpful?

Solution

Speed test: exists() vs. get() + try/except

Test functions in test.py:

from testapp.models import User

def exists(x):
    return User.objects.filter(pk=x).exists()

def get(x):
    try:
        User.objects.get(pk=x)
        return True
    except User.DoesNotExist:
        return False

Using timeit in shell:

In [1]: from testapp import test
In [2]: %timeit for x in range(100): test.exists(x)
10 loops, best of 3: 88.4 ms per loop
In [3]: %timeit for x in range(100): test.get(x)
10 loops, best of 3: 105 ms per loop
In [4]: timeit for x in range(1000): test.exists(x)
1 loops, best of 3: 880 ms per loop
In [5]: timeit for x in range(1000): test.get(x)
1 loops, best of 3: 1.02 s per loop

Conclusion: exists() is over 10% faster for checking if an object has been saved in the database.

OTHER TIPS

If you don't need the user, the first one is more efficient, as it doesn't instantiate the object.

I would say .exists() is the better way of doing it if you're simply trying to determine if an object matching the filter exists. The reason is because your example for .get() only covers 2 of the 3 scenarios. There's also the MultipleObjectsReturned exception which is raised when more than 1 object is found matching the filter.

I would use .get() for fetching a single instance and use the except clauses to catch the exception workflows.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top