Skip to content

Commit

Permalink
Fixed #12152. DoesNotExist and MultipleObjectsReturned now subclass t…
Browse files Browse the repository at this point in the history
…heir parent model's exceptions. Thanks, mattmcc and Alex Gaynor.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12567 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
jkocherhans committed Feb 24, 2010
1 parent de1ff3e commit 1089bda
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 8 deletions.
20 changes: 12 additions & 8 deletions django/db/models/base.py
Expand Up @@ -52,10 +52,14 @@ def __new__(cls, name, bases, attrs):

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
Expand Down Expand Up @@ -919,8 +923,8 @@ def model_unpickle(model, attrs, factory):

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 changes: 41 additions & 0 deletions tests/modeltests/model_inheritance/models.py
Expand Up @@ -38,6 +38,9 @@ class Student(CommonInfo):
class Meta:
pass

class StudentWorker(Student, Worker):
pass

#
# Abstract base classes with related models
#
Expand Down Expand Up @@ -176,6 +179,32 @@ def __unicode__(self):
...
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()
Expand Down Expand Up @@ -267,6 +296,18 @@ def __unicode__(self):
...
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')
Expand Down
20 changes: 20 additions & 0 deletions tests/modeltests/proxy_models/models.py
Expand Up @@ -206,6 +206,26 @@ class Meta:
>>> 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
Expand Down

0 comments on commit 1089bda

Please sign in to comment.