Fixed #12152. DoesNotExist and MultipleObjectsReturned now subclass their 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
This commit is contained in:
Joseph Kocherhans 2010-02-24 14:32:11 +00:00
parent de1ff3e51d
commit 1089bda546
3 changed files with 73 additions and 8 deletions

View File

@ -52,10 +52,14 @@ class ModelBase(type):
new_class.add_to_class('_meta', Options(meta, **kwargs)) new_class.add_to_class('_meta', Options(meta, **kwargs))
if not abstract: if not abstract:
new_class.add_to_class('DoesNotExist', new_class.add_to_class('DoesNotExist', subclass_exception('DoesNotExist',
subclass_exception('DoesNotExist', ObjectDoesNotExist, module)) tuple(x.DoesNotExist
new_class.add_to_class('MultipleObjectsReturned', for x in parents if hasattr(x, '_meta') and not x._meta.abstract)
subclass_exception('MultipleObjectsReturned', MultipleObjectsReturned, module)) 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: if base_meta and not base_meta.abstract:
# Non-abstract child classes inherit some attributes from their # Non-abstract child classes inherit some attributes from their
# non-abstract parent (unless an ABC comes before it in the # non-abstract parent (unless an ABC comes before it in the
@ -919,8 +923,8 @@ model_unpickle.__safe_for_unpickle__ = True
if sys.version_info < (2, 5): if sys.version_info < (2, 5):
# Prior to Python 2.5, Exception was an old-style class # Prior to Python 2.5, Exception was an old-style class
def subclass_exception(name, parent, unused): def subclass_exception(name, parents, unused):
return types.ClassType(name, (parent,), {}) return types.ClassType(name, parents, {})
else: else:
def subclass_exception(name, parent, module): def subclass_exception(name, parents, module):
return type(name, (parent,), {'__module__': module}) return type(name, parents, {'__module__': module})

View File

@ -38,6 +38,9 @@ class Student(CommonInfo):
class Meta: class Meta:
pass pass
class StudentWorker(Student, Worker):
pass
# #
# Abstract base classes with related models # Abstract base classes with related models
# #
@ -176,6 +179,32 @@ Traceback (most recent call last):
... ...
AttributeError: type object 'CommonInfo' has no attribute 'objects' 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 # Create a Post
>>> post = Post(title='Lorem Ipsum') >>> post = Post(title='Lorem Ipsum')
>>> post.save() >>> post.save()
@ -267,6 +296,18 @@ Traceback (most recent call last):
... ...
DoesNotExist: ItalianRestaurant matching query does not exist. 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. # Related objects work just as they normally do.
>>> s1 = Supplier(name="Joe's Chickens", address='123 Sesame St') >>> s1 = Supplier(name="Joe's Chickens", address='123 Sesame St')

View File

@ -206,6 +206,26 @@ False
>>> MyPersonProxy.objects.all() >>> MyPersonProxy.objects.all()
[<MyPersonProxy: Bazza del Frob>, <MyPersonProxy: Foo McBar>, <MyPersonProxy: homer>] [<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... # And now for some things that shouldn't work...
# #
# All base classes must be non-abstract # All base classes must be non-abstract