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:
parent
c85e3d4a2a
commit
7592ca69af
|
@ -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()
|
||||
|
||||
|
|
Loading…
Reference in New Issue