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 😊
Top comments (4)
I think that explicit programming is very useful. Developers can understand easily what happens where. I added the UserPhones model to your code (I know this code isn't right. This just an example).
In the above code, we can catch exceptions easily.
ObjectDoesNotExist catches DoesNotExist exceptions for all models.
DoesNotExist raised by Django's ORM and it is a subclass of the ObjectDoesNotExist
There is also EmptyResultSet exception, but nobody recommends this exception.
You are right. Thanks for the suggestion. I have updated my blog post to include a similar example 👍
Strangely enough this way of using exceptions with DoesNotExist makes Pylance think the second clause is unreachable code. Any idea why?
I have added my ip address to the allowed host to be accessible through other computer, however this doesn't occur.