Django

Code

Changeset 7784

Show
Ignore:
Timestamp:
06/29/08 04:41:35 (3 months ago)
Author:
mtredinnick
Message:

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.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/db/models/base.py

    r7777 r7784  
    396396                    sub_obj._collect_sub_objects(seen_objs, self.__class__, related.field.null) 
    397397 
     398        # Handle any ancestors (for the model-inheritance case). We do this by 
     399        # traversing to the most remote parent classes -- those with no parents 
     400        # themselves -- and then adding those instances to the collection. That 
     401        # will include all the child instances down to "self". 
     402        parent_stack = self._meta.parents.values() 
     403        while parent_stack: 
     404            link = parent_stack.pop() 
     405            parent_obj = getattr(self, link.name) 
     406            if parent_obj._meta.parents: 
     407                parent_stack.extend(parent_obj._meta.parents.values()) 
     408                continue 
     409            # At this point, parent_obj is base class (no ancestor models). So 
     410            # delete it and all its descendents. 
     411            parent_obj._collect_sub_objects(seen_objs) 
     412 
    398413    def delete(self): 
    399414        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) 
  • django/trunk/tests/regressiontests/model_inheritance_regress/models.py

    r7763 r7784  
    132132[datetime.datetime(2008, 6, 1, 0, 0)] 
    133133 
     134# Regression test for #7276: calling delete() on a model with multi-table 
     135# inheritance should delete the associated rows from any ancestor tables, as 
     136# well as any descendent objects. 
     137 
     138>>> ident = ItalianRestaurant.objects.all()[0].id 
     139>>> Place.objects.get(pk=ident) 
     140<Place: Guido's All New House of Pasta the place> 
     141>>> xx = Restaurant.objects.create(name='a', address='xx', serves_hot_dogs=True, serves_pizza=False) 
     142 
     143# This should delete both Restuarants, plus the related places, plus the ItalianRestaurant. 
     144>>> Restaurant.objects.all().delete() 
     145 
     146>>> Place.objects.get(pk=ident) 
     147Traceback (most recent call last): 
     148... 
     149DoesNotExist: Place matching query does not exist. 
     150 
     151>>> ItalianRestaurant.objects.get(pk=ident) 
     152Traceback (most recent call last): 
     153... 
     154DoesNotExist: ItalianRestaurant matching query does not exist. 
     155 
    134156"""}