Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
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: http://code.djangoproject.com/svn/django/trunk@7784 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 493163963633e9746a1eaf84bc39c574e4432eb2 1 parent 2c1d6a8
@malcolmt malcolmt authored
View
15 django/db/models/base.py
@@ -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, link.name)
+ 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, self._meta.pk.attname)
View
22 tests/regressiontests/model_inheritance_regress/models.py
@@ -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.
+
"""}

0 comments on commit 4931639

Please sign in to comment.
Something went wrong with that request. Please try again.