how to catch the MultipleObjectsReturned error in django
Solution 1
This isn't the best practice. You can technically do this without using exceptions. Did you intend to use Location
and Car
in this example?
You can do this:
Location.objects.filter(name='Paul').order_by('id').first()
I strongly suggest you read the Django QuerySet API reference.
https://docs.djangoproject.com/en/1.8/ref/models/querysets/
To answer your question about where the exception exists -- you can always access these QuerySet exceptions on the model itself. E.g. Location.DoesNotExist
and Location.MultipleObjectsReturned
. You don't need to import them if you already have the model imported.
Solution 2
Use a filter:
Location.objects.filter(name='Paul').first()
Or import the exception:
from django.core.exceptions import MultipleObjectsReturned
...
try:
Location.objects.get(name='Paul')
except MultipleObjectsReturned:
Location.objects.filter(name='Paul').first()
Solution 3
This is more pythonic way to do it.
try:
Location.objects.get(name='Paul')
except Location.MultipleObjectsReturned:
Location.objects.filter(name='Paul')[0]
Solution 4
Actually, even if we use MyModel.objects.get_or_create(...)
, there is still chances for creation of multiple instances due to race conditions. So, when we have to use MyModel.objects.get
or MyModel.objects.get_or_create
, we still have to expect return of multiple objects.
To handle this:
from django.core.exceptions import MultipleObjectsReturned
try:
obj,is_created=MyModel.objects.get_or_create(....)
except MultipleObjectsReturned as e:
# handle the case as you need here
pass
Solution 5
Use get when you know there is only one object that matches your query. If no items match the query, get() will raise a DoesNotExist exception. If multiple items matches the query, get() will raise a MultipleObjectsReturned exception. Use get() like this:
try:
one_entry = Entry.objects.get(blog=2000)
except Entry.DoesNotExist:
# query did not match to any item.
pass
except Entry.MultipleObjectsReturned:
# query matched multiple items.
pass
else:
# query matched to just one item
print(one_entry)
Comments
-
Tom over 2 years
Is it possible to catch the
MultipleObjectsReturned
error in Django?I do a searchquery and if there are more than one objects I want that the first in the list will be taken so I tried this:
try: Location.objects.get(name='Paul') except MultipleObjectsReturned: Location.objects.get(name='Paul')[0]
However, it exists in the doc though
global variable MultipleObjectsReturned does not exist
-
Tom over 8 yearsyeah true! sorry, meant Location both times. Why is using exceptions not the best practice?
-
veggie1 over 8 yearsThen what you probably want is just
Location.objects.filter(name='Paul').order_by('id').first()
. It returns None if there isn't a record with that name. I updated the answer. Using exceptions in this case is unneccessary. Instead of causing an exception to be thrown, you can still have a happy path without raising any errors. -
RemcoGerlich over 7 yearsThis isn't actually an answer to the question.
-
RemcoGerlich over 7 yearsYou mean
filter
, but at least it does answer how to catch the exception. -
Vaseem Ahmed Khan over 7 years@RemcoGerlich yes it filters or return object according to query. get return object whereas .filter returns queryset.
-
AlanSE about 7 years@VaseemAhmedKhan The answer should be updated to do
Location.objects.filter(name='Paul')[0]
, otherwise the except block will result in the same exception being thrown. You need a queryset because that contains the logic about which object to return, for instanceLocation.objects.get(name='Paul').order_by('age')[0]
will return the youngest Paul in the database. This is how you return the correct Paul, according to your business logic. -
jojo over 6 yearsNote:
Location.objects.get(name='Paul')[0]
will raiseMultipleObjectsReturned
again. UseLocation.objects.filter(name='Paul').first()
instead. -
lcary almost 6 years"This isn't the best practice." Are you sure catching the exception isn't best practices? I think it might be best practice in Python. According to "EAFP" in docs.python.org/3/glossary.html, I think stackoverflow.com/a/32173014/2573242 is the correct answer here.
-
Paulo Fabrício almost 5 yearsIt doesn't work in older versions of Django like 1.5. Using first() gives AttributeError. I had to import MultipleObjectsReturned instead.
-
Greg Schmit over 4 years@AlanSE No, the exception block will not throw the same exception. It might throw a
DoesNotExist
exception, but notMultipleObjectsReturned
.