TIMEX
TIMEX

Reputation: 271624

What's the best way to handle Django's objects.get?

Whenever I do this:

thepost = Content.objects.get(name="test")

It always throws an error when nothing is found. How do I handle it?

Upvotes: 70

Views: 63033

Answers (9)

heunle
heunle

Reputation: 1

it's good to keep an eye on this exception too .

one important exception to consider with object.get() is MultipleObjectsReturned


from django.core.exceptions import MultipleObjectsReturned

try:
    model.objects.get(...)
except MultipleObjectsReturned:
    #enter your error handeling in here
    

the get() will raise MultipleObjectsReturned if more than one object is found in the database. but get() is meant to be only for retrieving ONE object , more than that is meant for filter()

Upvotes: 0

Giorgos Myrianthous
Giorgos Myrianthous

Reputation: 39800

There are essentially two ways you can do this. The first approach is more verbose as it doesn't use any shortcuts:

from django.http import Http404
from .models import Content    


try:
    thepost = Content.objects.get(name="test")
except Content.DoesNotExist:
    raise Http404("Content does not exist")

Now since this sort of operation (i.e. get an object or raise 404 if it does not exist) is quite common in Web Development, Django offers a shortcut called get_object_or_404 that will get() the requested object or raise Http404 in case it is not found:

from django.shortcuts import get_object_or_404
from .models import Content


thepost = get_object_or_404(Content, name="test")

Likewise for lists of objects, you can use get_list_or_404() function that makes use of filter() instead of get() and in case the returned list is empty, Http404 will be raised.

Upvotes: 4

Some programmer dude
Some programmer dude

Reputation: 409146

try:
    thepost = Content.objects.get(name="test")
except Content.DoesNotExist:
    thepost = None

Use the model DoesNotExist exception

Upvotes: 122

Rob Golding
Rob Golding

Reputation: 3562

Often, it is more useful to use the Django shortcut function get_object_or_404 instead of the API directly:

from django.shortcuts import get_object_or_404

thepost = get_object_or_404(Content, name='test')

Fairly obviously, this will throw a 404 error if the object cannot be found, and your code will continue if it is successful.

Upvotes: 38

Rafael Valverde
Rafael Valverde

Reputation: 301

Another way of writing:

try:
    thepost = Content.objects.get(name="test")
except Content.DoesNotExist:
    thepost = None

is simply:

thepost = Content.objects.filter(name="test").first()

Note that the two are not strictly the same. Manager method get will raise not only an exception in the case there's no record you're querying for but also when multiple records are found. Using first when there are more than one record might fail your business logic silently by returning the first record.

Upvotes: 12

Mahammad Adil Azeem
Mahammad Adil Azeem

Reputation: 9392

Handling exceptions at different points in your views could really be cumbersome..What about defining a custom Model Manager, in the models.py file, like

class ContentManager(model.Manager):
    def get_nicely(self, **kwargs):
        try:
            return self.get(kwargs)
        except(KeyError, Content.DoesNotExist):
            return None

and then including it in the content Model class

class Content(model.Model):
    ...
    objects = ContentManager()

In this way it can be easily dealt in the views i.e.

post = Content.objects.get_nicely(pk = 1)
if post != None:
    # Do something
else:
    # This post doesn't exist

Upvotes: 4

Banjer
Banjer

Reputation: 8300

Raising a Http404 exception works great:

from django.http import Http404

def detail(request, poll_id):
    try:
        p = Poll.objects.get(pk=poll_id)
    except Poll.DoesNotExist:
        raise Http404
    return render_to_response('polls/detail.html', {'poll': p})

Upvotes: 3

zobbo
zobbo

Reputation: 246

You can also catch a generic DoesNotExist. As per the docs at http://docs.djangoproject.com/en/dev/ref/models/querysets/

from django.core.exceptions import ObjectDoesNotExist
try:
    e = Entry.objects.get(id=3)
    b = Blog.objects.get(id=1)
except ObjectDoesNotExist:
    print "Either the entry or blog doesn't exist."

Upvotes: 19

Anurag Uniyal
Anurag Uniyal

Reputation: 88737

Catch the exception

try:
    thepost = Content.objects.get(name="test")
except Content.DoesNotExist:
    thepost = None

alternatively you can filter, which will return a empty list if nothing matches

posts = Content.objects.filter(name="test")
if posts:
    # do something with posts[0] and see if you want to raise error if post > 1

Upvotes: 8

Related Questions