Commit 18c800f1 authored by Joseph Kocherhans's avatar Joseph Kocherhans
Browse files

[1.1.X] Fixed #12152. DoesNotExist and MultipleObjectsReturned now subclass...

[1.1.X] Fixed #12152. DoesNotExist and MultipleObjectsReturned now subclass their parent model's exceptions. Backport of r12567 from trunk.


git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.1.X@12568 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent fbe455e1
Loading
Loading
Loading
Loading
+12 −8
Original line number Diff line number Diff line
@@ -55,10 +55,14 @@ class ModelBase(type):

        new_class.add_to_class('_meta', Options(meta, **kwargs))
        if not abstract:
            new_class.add_to_class('DoesNotExist',
                    subclass_exception('DoesNotExist', ObjectDoesNotExist, module))
            new_class.add_to_class('MultipleObjectsReturned',
                    subclass_exception('MultipleObjectsReturned', MultipleObjectsReturned, module))
            new_class.add_to_class('DoesNotExist', subclass_exception('DoesNotExist',
                    tuple(x.DoesNotExist
                            for x in parents if hasattr(x, '_meta') and not x._meta.abstract)
                                    or (ObjectDoesNotExist,), module))
            new_class.add_to_class('MultipleObjectsReturned', subclass_exception('MultipleObjectsReturned',
                    tuple(x.MultipleObjectsReturned
                            for x in parents if hasattr(x, '_meta') and not x._meta.abstract)
                                    or (MultipleObjectsReturned,), module))
            if base_meta and not base_meta.abstract:
                # Non-abstract child classes inherit some attributes from their
                # non-abstract parent (unless an ABC comes before it in the
@@ -681,8 +685,8 @@ model_unpickle.__safe_for_unpickle__ = True

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, parents, unused):
        return types.ClassType(name, parents, {})
else:
    def subclass_exception(name, parent, module):
        return type(name, (parent,), {'__module__': module})
    def subclass_exception(name, parents, module):
        return type(name, parents, {'__module__': module})
+41 −0
Original line number Diff line number Diff line
@@ -38,6 +38,9 @@ class Student(CommonInfo):
    class Meta:
        pass

class StudentWorker(Student, Worker):
    pass

#
# Abstract base classes with related models
#
@@ -151,6 +154,32 @@ Traceback (most recent call last):
    ...
AttributeError: type object 'CommonInfo' has no attribute 'objects'

# A StudentWorker which does not exist is both a Student and Worker which does not exist.
>>> try:
...     StudentWorker.objects.get(id=1)
... except Student.DoesNotExist:
...     pass
>>> try:
...     StudentWorker.objects.get(id=1)
... except Worker.DoesNotExist:
...     pass

# MultipleObjectsReturned is also inherited.
>>> sw1 = StudentWorker()
>>> sw1.name = 'Wilma'
>>> sw1.age = 35
>>> sw1.save()
>>> sw2 = StudentWorker()
>>> sw2.name = 'Betty'
>>> sw2.age = 34
>>> sw2.save()
>>> try:
...     StudentWorker.objects.get(id__lt=10)
... except Student.MultipleObjectsReturned:
...     pass
... except Worker.MultipleObjectsReturned:
...     pass

# Create a Post
>>> post = Post(title='Lorem Ipsum')
>>> post.save()
@@ -242,6 +271,18 @@ Traceback (most recent call last):
    ...
DoesNotExist: ItalianRestaurant matching query does not exist.

# An ItalianRestaurant which does not exist is also a Place which does not exist.
>>> try:
...     ItalianRestaurant.objects.get(name='The Noodle Void')
... except Place.DoesNotExist:
...     pass

# MultipleObjectsReturned is also inherited.
>>> try:
...     Restaurant.objects.get(id__lt=10)
... except Place.MultipleObjectsReturned:
...     pass

# Related objects work just as they normally do.

>>> s1 = Supplier(name="Joe's Chickens", address='123 Sesame St')
+20 −0
Original line number Diff line number Diff line
@@ -205,6 +205,26 @@ False
>>> MyPersonProxy.objects.all()
[<MyPersonProxy: Bazza del Frob>, <MyPersonProxy: Foo McBar>, <MyPersonProxy: homer>]

# Proxy models are included in the ancestors for a model's DoesNotExist and MultipleObjectsReturned
>>> try:
...     MyPersonProxy.objects.get(name='Zathras')
... except Person.DoesNotExist:
...     pass
>>> try:
...     MyPersonProxy.objects.get(id__lt=10)
... except Person.MultipleObjectsReturned:
...     pass
>>> try:
...     StatusPerson.objects.get(name='Zathras')
... except Person.DoesNotExist:
...     pass
>>> sp1 = StatusPerson.objects.create(name='Bazza Jr.')
>>> sp2 = StatusPerson.objects.create(name='Foo Jr.')
>>> try:
...     StatusPerson.objects.get(id__lt=10)
... except Person.MultipleObjectsReturned:
...     pass

# And now for some things that shouldn't work...
#
# All base classes must be non-abstract