Wednesday, September 15, 2010

Using ObjectDoesNotExist to catch DoesNotExist errors

The Django documentation discusses the DoesNotExist error as follows:
get() raises a DoesNotExist exception if an object wasn't found for the given parameters. This exception is also an attribute of the model class. Example:

Entry.objects.get(id='foo') # raises Entry.DoesNotExist

The DoesNotExist exception inherits from django.core.exceptions.ObjectDoesNotExist, so you can target multiple DoesNotExist exceptions.
How does it actually work? The Stack Overflow thread has this discussion:

If you dig through the file, you see these lines:
class ModelBase(type):

     super_new = super(ModelBase, cls).__new__
     new_class = super_new(cls, name, bases, {'__module__': module})

     if not abstract:
                    subclass_exception('DoesNotExist', ObjectDoesNotExist, module))
                    subclass_exception('MultipleObjectsReturned', MultipleObjectsReturned, module))

   def add_to_class(cls, name, value):
        if hasattr(value, 'contribute_to_class'):
            value.contribute_to_class(cls, name)
            setattr(cls, name, value)

You then have to wade through the bottom of the file to see what subclass_exception() actually does:
if sys.version_info < (2, 5):
    # Prior to Python 2.5, Exception was an old-style class                                                                                                                                                                                  
    def subclass_exception(name, parent, unused):
        return types.ClassType(name, (parent,), {})
    def subclass_exception(name, parent, module):
        return type(name, (parent,), {'__module__': module})
It seems that Django creates a DoesNotExist exception for the class itself dynamically. The parent object is ObjectDoesNotExist, so you can use that parent to be able to catch exceptions thrown by multiple classes.

No comments:

Post a Comment