Ticket #1007: restrict_delete-0.95.1.2.diff
File restrict_delete-0.95.1.2.diff, 4.1 KB (added by , 18 years ago) |
---|
-
db/models/options.py
13 13 14 14 DEFAULT_NAMES = ('verbose_name', 'db_table', 'ordering', 15 15 'unique_together', 'permissions', 'get_latest_by', 16 'order_with_respect_to', 'app_label' )16 'order_with_respect_to', 'app_label', 'restrict_delete') 17 17 18 18 class Options(object): 19 19 def __init__(self, meta): … … 33 33 self.has_auto_field = False 34 34 self.one_to_one_field = None 35 35 self.parents = [] 36 self.restrict_delete = False 36 37 37 38 def contribute_to_class(self, cls, name): 38 39 cls._meta = self -
db/models/base.py
1 1 import django.db.models.manipulators 2 2 import django.db.models.manager 3 3 from django.core import validators 4 from django.core.exceptions import ObjectDoesNotExist 4 from django.core.exceptions import ObjectDoesNotExist, IntegrityError 5 5 from django.db.models.fields import AutoField, ImageField, FieldDoesNotExist 6 6 from django.db.models.fields.related import OneToOneRel, ManyToOneRel 7 7 from django.db.models.query import delete_objects … … 238 238 error_dict[f.name] = errors 239 239 return error_dict 240 240 241 def _collect_sub_objects(self, seen_objs ):241 def _collect_sub_objects(self, seen_objs, restrict_delete=False): 242 242 """ 243 243 Recursively populates seen_objs with all objects related to this object. 244 244 When done, seen_objs will be in the format: … … 250 250 return 251 251 seen_objs.setdefault(self.__class__, {})[pk_val] = self 252 252 253 for related in self._meta.get_all_related_objects(): 253 has_nonfollows = False 254 for related in self._meta.get_all_related_objects(): 254 255 rel_opts_name = related.get_accessor_name() 255 256 if isinstance(related.field.rel, OneToOneRel): 256 257 try: … … 258 259 except ObjectDoesNotExist: 259 260 pass 260 261 else: 262 # If the item in question isn't from a 'followed' field, don't continue - this should trigger RESTRICT. 263 if restrict_delete and not related.get_follow(): 264 has_nonfollows = True 265 break 261 266 sub_obj._collect_sub_objects(seen_objs) 262 267 else: 268 # If we find a count for this relation and the field is not a 'followed' one, trigger RESTRICT. 269 if restrict_delete and not related.get_follow() and getattr(self,rel_opts_name).count(): 270 has_nonfollows=True 271 break 263 272 for sub_obj in getattr(self, rel_opts_name).all(): 264 273 sub_obj._collect_sub_objects(seen_objs) 265 274 275 # This will only be true if restrict_delete is True and we found related non-followed objects 276 if has_nonfollows: 277 raise IntegrityError, "The requested object could not be deleted because it is referenced by other objects." 278 279 266 280 def delete(self): 267 281 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) 268 282 269 283 # Find all the objects than need to be deleted 270 284 seen_objs = SortedDict() 271 self._collect_sub_objects(seen_objs )285 self._collect_sub_objects(seen_objs,self._meta.restrict_delete) 272 286 273 287 # Actually delete the objects 274 288 delete_objects(seen_objs) -
core/exceptions.py
23 23 class ImproperlyConfigured(Exception): 24 24 "Django is somehow improperly configured" 25 25 pass 26 27 class IntegrityError(Exception): 28 "The requested object could not be deleted because it is referenced by other objects" 29 pass