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
This commit is contained in:
parent
2c1d6a80b3
commit
4931639636
|
@ -395,6 +395,21 @@ class Model(object):
|
|||
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)
|
||||
|
||||
|
|
|
@ -131,4 +131,26 @@ __test__ = {'API_TESTS':"""
|
|||
>>> 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.
|
||||
|
||||
"""}
|
||||
|
|
Loading…
Reference in New Issue