mirror of
https://github.com/django/django.git
synced 2025-06-05 03:29:12 +00:00
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
|
save.alters_data = True
|
||||||
|
|
||||||
def __collect_sub_objects(self, seen_objs):
|
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()
|
pk_val = self._get_pk_val()
|
||||||
|
|
||||||
if pk_val in seen_objs.setdefault(self.__class__, {}):
|
if pk_val in seen_objs.setdefault(self.__class__, {}):
|
||||||
return
|
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():
|
for related in self._meta.get_all_related_objects():
|
||||||
rel_opts_name = related.get_method_name_part()
|
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)():
|
for sub_obj in getattr(self, 'get_%s_list' % rel_opts_name)():
|
||||||
sub_obj.__collect_sub_objects(seen_objs)
|
sub_obj.__collect_sub_objects(seen_objs)
|
||||||
|
|
||||||
def delete(self, ignore_objects=None):
|
def delete(self):
|
||||||
assert self._get_pk_val() is not None, "%r can't be deleted because it doesn't have an ID."
|
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 = {}
|
|
||||||
if ignore_objects:
|
|
||||||
for obj in ignore_objects:
|
|
||||||
ignore_objs.setdefault(self.__class__,{})[obj._get_pk_val()] = (obj, False)
|
|
||||||
|
|
||||||
seen_objs = {}
|
seen_objs = {}
|
||||||
self.__collect_sub_objects(seen_objs)
|
self.__collect_sub_objects(seen_objs)
|
||||||
|
|
||||||
#TODO: create a total class ordering rather than this sorting, which is
|
seen_classes = set(seen_objs.keys())
|
||||||
# only a partial ordering, and also is done each delete..
|
ordered_classes = list(seen_classes)
|
||||||
seen_cls = set(seen_objs.keys())
|
ordered_classes.sort(cmp_cls)
|
||||||
cls_order = list(seen_cls)
|
|
||||||
cls_order.sort(cmp_cls)
|
|
||||||
|
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
|
|
||||||
for cls in cls_order:
|
for cls in ordered_classes:
|
||||||
seen_objs[cls] = seen_objs[cls].items()
|
seen_objs[cls] = seen_objs[cls].items()
|
||||||
seen_objs[cls].sort()
|
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.
|
for related in cls._meta.get_all_related_many_to_many_objects():
|
||||||
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:
|
|
||||||
cursor.execute("DELETE FROM %s WHERE %s=%%s" % \
|
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])
|
[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)
|
for cls in ordered_classes:
|
||||||
|
seen_objs[cls].reverse()
|
||||||
dispatcher.send(signal=signals.post_delete, sender=cls, instance=instance)
|
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()
|
connection.commit()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user