Anže Pečar
Posted on November 9, 2019
In Django it's very common to see code like this:
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from myproject.apps.teams.models import Team
try:
user = User.objects.get(pk=1337)
phone = Team.objects.get(pk=1337)
except ObjectDoesNotExist:
logging.error("User or Team does not exist")
The code will try to fetch an auth user and a team from the database and if either of those does not exist, we'll just log an error. This is so common that I never thought twice when seeing or writing it.
But it turns out that there is a slightly better way to accomplish the same result. I didn't know this before recently, but the Django Model class has its own DoesNotExist
exception! We can use it like this:
from django.contrib.auth.models import User
from myproject.apps.teams.models import Team
try:
user = User.objects.get(pk=1337)
phone = Phone.objects.get(pk=1337)
except User.DoesNotExist:
logging.error("User does not exist")
except Phone.DoesNotExist:
logging.error("Phone does not exist")
This is better for a couple of reasons:
- The two except blocks are now more explicit and will only catch exceptions when the specific model does not exist.
- This is minor, but you don't have to worry if ObjectDoesNotExist is already imported in the current scope or not.
MultipleObjectsReturned
exception is implemented the exact same way and if you are curious to learn how Django implements a new Exception type for every subclass that you make, you can check out the source code here.
My day job codebase currently has 231 occurrences of except ObjectDoesNotExist. I'll slowly start replacing them with model.DoesNotExist 😊
Posted on November 9, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.