magic-removal: Removed ignore_objects argument to delete() and added some docs and comments to that function

git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2041 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2006-01-17 22:01:14 +00:00
parent c85e3d4a2a
commit 7592ca69af
1 changed files with 37 additions and 47 deletions

View File

@ -190,11 +190,16 @@ class Model(object):
save.alters_data = True
def __collect_sub_objects(self, seen_objs):
"""
Recursively populates seen_objs with all objects related to this object.
When done, seen_objs will be in the format:
{model_class: {pk_val: obj, pk_val: obj, ...},
model_class: {pk_val: obj, pk_val: obj, ...}, ...}
"""
pk_val = self._get_pk_val()
if pk_val in seen_objs.setdefault(self.__class__, {}):
return
seen_objs.setdefault(self.__class__, {})[pk_val] = (self, True)
seen_objs.setdefault(self.__class__, {})[pk_val] = self
for related in self._meta.get_all_related_objects():
rel_opts_name = related.get_method_name_part()
@ -209,63 +214,48 @@ class Model(object):
for sub_obj in getattr(self, 'get_%s_list' % rel_opts_name)():
sub_obj.__collect_sub_objects(seen_objs)
def delete(self, ignore_objects=None):
assert self._get_pk_val() is not None, "%r can't be deleted because it doesn't have an ID."
seen_objs = {}
if ignore_objects:
for obj in ignore_objects:
ignore_objs.setdefault(self.__class__,{})[obj._get_pk_val()] = (obj, False)
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)
seen_objs = {}
self.__collect_sub_objects(seen_objs)
#TODO: create a total class ordering rather than this sorting, which is
# only a partial ordering, and also is done each delete..
seen_cls = set(seen_objs.keys())
cls_order = list(seen_cls)
cls_order.sort(cmp_cls)
seen_classes = set(seen_objs.keys())
ordered_classes = list(seen_classes)
ordered_classes.sort(cmp_cls)
cursor = connection.cursor()
for cls in cls_order:
for cls in ordered_classes:
seen_objs[cls] = seen_objs[cls].items()
seen_objs[cls].sort()
for pk_val, (instance, do_delete) in seen_objs[cls]:
for pk_val, instance in seen_objs[cls]:
dispatcher.send(signal=signals.pre_delete, sender=cls, instance=instance)
# Run any pre-delete hooks.
if do_delete:
dispatcher.send(signal=signals.pre_delete, sender=cls, instance=instance)
for related in cls._meta.get_all_related_many_to_many_objects():
cursor.execute("DELETE FROM %s WHERE %s=%%s" % \
(backend.quote_name(related.field.get_m2m_db_table(related.opts)),
backend.quote_name(cls._meta.object_name.lower() + '_id')),
[pk_val])
for f in cls._meta.many_to_many:
cursor.execute("DELETE FROM %s WHERE %s=%%s" % \
(backend.quote_name(f.get_m2m_db_table(cls._meta)),
backend.quote_name(cls._meta.object_name.lower() + '_id')),
[pk_val])
for field in cls._meta.fields:
if field.rel and field.null and field.rel.to in seen_cls:
cursor.execute("UPDATE %s SET %s = NULL WHERE %s=%%s" % \
(backend.quote_name(cls._meta.db_table), backend.quote_name(field.column),
backend.quote_name(cls._meta.pk.column)), [pk_val])
setattr(instance, field.attname, None)
for cls in cls_order:
seen_objs[cls].reverse()
for pk_val, (instance, do_delete) in seen_objs[cls]:
if do_delete:
for related in cls._meta.get_all_related_many_to_many_objects():
cursor.execute("DELETE FROM %s WHERE %s=%%s" % \
(backend.quote_name(cls._meta.db_table), backend.quote_name(cls._meta.pk.column)),
(backend.quote_name(related.field.get_m2m_db_table(related.opts)),
backend.quote_name(cls._meta.object_name.lower() + '_id')),
[pk_val])
for f in cls._meta.many_to_many:
cursor.execute("DELETE FROM %s WHERE %s=%%s" % \
(backend.quote_name(f.get_m2m_db_table(cls._meta)),
backend.quote_name(cls._meta.object_name.lower() + '_id')),
[pk_val])
for field in cls._meta.fields:
if field.rel and field.null and field.rel.to in seen_classes:
cursor.execute("UPDATE %s SET %s=NULL WHERE %s=%%s" % \
(backend.quote_name(cls._meta.db_table), backend.quote_name(field.column),
backend.quote_name(cls._meta.pk.column)), [pk_val])
setattr(instance, field.attname, None)
setattr(instance, cls._meta.pk.attname, None)
dispatcher.send(signal=signals.post_delete, sender=cls, instance=instance)
for cls in ordered_classes:
seen_objs[cls].reverse()
for pk_val, instance in seen_objs[cls]:
cursor.execute("DELETE FROM %s WHERE %s=%%s" % \
(backend.quote_name(cls._meta.db_table), backend.quote_name(cls._meta.pk.column)),
[pk_val])
setattr(instance, cls._meta.pk.attname, None)
dispatcher.send(signal=signals.post_delete, sender=cls, instance=instance)
connection.commit()