How do I get the object if it exists, or None if it does not exist in Django?

When I ask the model manager to get an object, it raises DoesNotExist when there is no matching object.

go = Content.objects.get(name="baby")

Instead of DoesNotExist, how can I have go be None instead?


Solution 1:

There is no 'built in' way to do this. Django will raise the DoesNotExist exception every time. The idiomatic way to handle this in python is to wrap it in a try catch:

try:
    go = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
    go = None

What I did do, is to subclass models.Manager, create a safe_get like the code above and use that manager for my models. That way you can write: SomeModel.objects.safe_get(foo='bar').

Solution 2:

Since django 1.6 you can use first() method like so:

Content.objects.filter(name="baby").first()

Solution 3:

From django docs

get() raises a DoesNotExist exception if an object is not found for the given parameters. This exception is also an attribute of the model class. The DoesNotExist exception inherits from django.core.exceptions.ObjectDoesNotExist

You can catch the exception and assign None to go.

from django.core.exceptions import ObjectDoesNotExist
try:
    go  = Content.objects.get(name="baby")
except ObjectDoesNotExist:
    go = None

Solution 4:

You can create a generic function for this.

def get_or_none(classmodel, **kwargs):
    try:
        return classmodel.objects.get(**kwargs)
    except classmodel.DoesNotExist:
        return None

Use this like below:

go = get_or_none(Content,name="baby")

go will be None if no entry matches else will return the Content entry.

Note:It will raises exception MultipleObjectsReturned if more than one entry returned for name="baby".

You should handle it on the data model to avoid this kind of error but you may prefer to log it at run time like this:

def get_or_none(classmodel, **kwargs):
    try:
        return classmodel.objects.get(**kwargs)
    except classmodel.MultipleObjectsReturned as e:
        print('ERR====>', e)

    except classmodel.DoesNotExist:
        return None

Solution 5:

You can do it this way:

go  = Content.objects.filter(name="baby").first()

Now go variable could be either the object you want or None

Ref: https://docs.djangoproject.com/en/1.8/ref/models/querysets/#django.db.models.query.QuerySet.first