Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #7276 -- Delete multi-table objects correctly.

When model inheritance is used, the parent objects should be deleted as part of
the delete() call on the child.

git-svn-id: bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 493163963633e9746a1eaf84bc39c574e4432eb2 1 parent 2c1d6a8
Malcolm Tredinnick malcolmt authored
15 django/db/models/
@@ -395,6 +395,21 @@ def _collect_sub_objects(self, seen_objs, parent=None, nullable=False):
for sub_obj in getattr(self, rel_opts_name).all():
sub_obj._collect_sub_objects(seen_objs, self.__class__, related.field.null)
+ # Handle any ancestors (for the model-inheritance case). We do this by
+ # traversing to the most remote parent classes -- those with no parents
+ # themselves -- and then adding those instances to the collection. That
+ # will include all the child instances down to "self".
+ parent_stack = self._meta.parents.values()
+ while parent_stack:
+ link = parent_stack.pop()
+ parent_obj = getattr(self,
+ if parent_obj._meta.parents:
+ parent_stack.extend(parent_obj._meta.parents.values())
+ continue
+ # At this point, parent_obj is base class (no ancestor models). So
+ # delete it and all its descendents.
+ parent_obj._collect_sub_objects(seen_objs)
def delete(self):
assert self._get_pk_val() is not None, "%s object can't be deleted because its %s attribute is set to None." % (self._meta.object_name,
22 tests/regressiontests/model_inheritance_regress/
@@ -131,4 +131,26 @@ class Child(Parent):
>>> Child.objects.dates('created', 'month')
[datetime.datetime(2008, 6, 1, 0, 0)]
+# Regression test for #7276: calling delete() on a model with multi-table
+# inheritance should delete the associated rows from any ancestor tables, as
+# well as any descendent objects.
+>>> ident = ItalianRestaurant.objects.all()[0].id
+>>> Place.objects.get(pk=ident)
+<Place: Guido's All New House of Pasta the place>
+>>> xx = Restaurant.objects.create(name='a', address='xx', serves_hot_dogs=True, serves_pizza=False)
+# This should delete both Restuarants, plus the related places, plus the ItalianRestaurant.
+>>> Restaurant.objects.all().delete()
+>>> Place.objects.get(pk=ident)
+Traceback (most recent call last):
+DoesNotExist: Place matching query does not exist.
+>>> ItalianRestaurant.objects.get(pk=ident)
+Traceback (most recent call last):
+DoesNotExist: ItalianRestaurant matching query does not exist.
Please sign in to comment.
Something went wrong with that request. Please try again.