Skip to content

Commit 1089bda

Browse files
committed
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
1 parent de1ff3e commit 1089bda

File tree

3 files changed

+73
-8
lines changed

3 files changed

+73
-8
lines changed

django/db/models/base.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,14 @@ def __new__(cls, name, bases, attrs):
5252

5353
new_class.add_to_class('_meta', Options(meta, **kwargs))
5454
if not abstract:
55-
new_class.add_to_class('DoesNotExist',
56-
subclass_exception('DoesNotExist', ObjectDoesNotExist, module))
57-
new_class.add_to_class('MultipleObjectsReturned',
58-
subclass_exception('MultipleObjectsReturned', MultipleObjectsReturned, module))
55+
new_class.add_to_class('DoesNotExist', subclass_exception('DoesNotExist',
56+
tuple(x.DoesNotExist
57+
for x in parents if hasattr(x, '_meta') and not x._meta.abstract)
58+
or (ObjectDoesNotExist,), module))
59+
new_class.add_to_class('MultipleObjectsReturned', subclass_exception('MultipleObjectsReturned',
60+
tuple(x.MultipleObjectsReturned
61+
for x in parents if hasattr(x, '_meta') and not x._meta.abstract)
62+
or (MultipleObjectsReturned,), module))
5963
if base_meta and not base_meta.abstract:
6064
# Non-abstract child classes inherit some attributes from their
6165
# non-abstract parent (unless an ABC comes before it in the
@@ -919,8 +923,8 @@ def model_unpickle(model, attrs, factory):
919923

920924
if sys.version_info < (2, 5):
921925
# Prior to Python 2.5, Exception was an old-style class
922-
def subclass_exception(name, parent, unused):
923-
return types.ClassType(name, (parent,), {})
926+
def subclass_exception(name, parents, unused):
927+
return types.ClassType(name, parents, {})
924928
else:
925-
def subclass_exception(name, parent, module):
926-
return type(name, (parent,), {'__module__': module})
929+
def subclass_exception(name, parents, module):
930+
return type(name, parents, {'__module__': module})

tests/modeltests/model_inheritance/models.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ class Student(CommonInfo):
3838
class Meta:
3939
pass
4040

41+
class StudentWorker(Student, Worker):
42+
pass
43+
4144
#
4245
# Abstract base classes with related models
4346
#
@@ -176,6 +179,32 @@ def __unicode__(self):
176179
...
177180
AttributeError: type object 'CommonInfo' has no attribute 'objects'
178181
182+
# A StudentWorker which does not exist is both a Student and Worker which does not exist.
183+
>>> try:
184+
... StudentWorker.objects.get(id=1)
185+
... except Student.DoesNotExist:
186+
... pass
187+
>>> try:
188+
... StudentWorker.objects.get(id=1)
189+
... except Worker.DoesNotExist:
190+
... pass
191+
192+
# MultipleObjectsReturned is also inherited.
193+
>>> sw1 = StudentWorker()
194+
>>> sw1.name = 'Wilma'
195+
>>> sw1.age = 35
196+
>>> sw1.save()
197+
>>> sw2 = StudentWorker()
198+
>>> sw2.name = 'Betty'
199+
>>> sw2.age = 34
200+
>>> sw2.save()
201+
>>> try:
202+
... StudentWorker.objects.get(id__lt=10)
203+
... except Student.MultipleObjectsReturned:
204+
... pass
205+
... except Worker.MultipleObjectsReturned:
206+
... pass
207+
179208
# Create a Post
180209
>>> post = Post(title='Lorem Ipsum')
181210
>>> post.save()
@@ -267,6 +296,18 @@ def __unicode__(self):
267296
...
268297
DoesNotExist: ItalianRestaurant matching query does not exist.
269298
299+
# An ItalianRestaurant which does not exist is also a Place which does not exist.
300+
>>> try:
301+
... ItalianRestaurant.objects.get(name='The Noodle Void')
302+
... except Place.DoesNotExist:
303+
... pass
304+
305+
# MultipleObjectsReturned is also inherited.
306+
>>> try:
307+
... Restaurant.objects.get(id__lt=10)
308+
... except Place.MultipleObjectsReturned:
309+
... pass
310+
270311
# Related objects work just as they normally do.
271312
272313
>>> s1 = Supplier(name="Joe's Chickens", address='123 Sesame St')

tests/modeltests/proxy_models/models.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,26 @@ class Meta:
206206
>>> MyPersonProxy.objects.all()
207207
[<MyPersonProxy: Bazza del Frob>, <MyPersonProxy: Foo McBar>, <MyPersonProxy: homer>]
208208
209+
# Proxy models are included in the ancestors for a model's DoesNotExist and MultipleObjectsReturned
210+
>>> try:
211+
... MyPersonProxy.objects.get(name='Zathras')
212+
... except Person.DoesNotExist:
213+
... pass
214+
>>> try:
215+
... MyPersonProxy.objects.get(id__lt=10)
216+
... except Person.MultipleObjectsReturned:
217+
... pass
218+
>>> try:
219+
... StatusPerson.objects.get(name='Zathras')
220+
... except Person.DoesNotExist:
221+
... pass
222+
>>> sp1 = StatusPerson.objects.create(name='Bazza Jr.')
223+
>>> sp2 = StatusPerson.objects.create(name='Foo Jr.')
224+
>>> try:
225+
... StatusPerson.objects.get(id__lt=10)
226+
... except Person.MultipleObjectsReturned:
227+
... pass
228+
209229
# And now for some things that shouldn't work...
210230
#
211231
# All base classes must be non-abstract

0 commit comments

Comments
 (0)