diff --git a/django/db/models/deletion.py b/django/db/models/deletion.py
index 3830052..77df47a 100644
a
|
b
|
class Collector(object):
|
78 | 78 | # parent. |
79 | 79 | self.dependencies = {} # {model: {models}} |
80 | 80 | |
| 81 | self.protected_errors = [] |
| 82 | |
81 | 83 | def add(self, objs, source=None, nullable=False, reverse_dependency=False): |
82 | 84 | """ |
83 | 85 | Adds 'objs' to the collection of objects to be deleted. If the call is |
… |
… |
class Collector(object):
|
216 | 218 | if self.can_fast_delete(sub_objs, from_field=field): |
217 | 219 | self.fast_deletes.append(sub_objs) |
218 | 220 | elif sub_objs: |
219 | | field.remote_field.on_delete(self, field, sub_objs, self.using) |
| 221 | try: |
| 222 | field.remote_field.on_delete(self, field, sub_objs, self.using) |
| 223 | except ProtectedError as e: |
| 224 | self.protected_errors.append(e) |
| 225 | |
220 | 226 | for field in model._meta.private_fields: |
221 | 227 | if hasattr(field, 'bulk_related_objects'): |
222 | 228 | # It's something like generic foreign key. |
223 | 229 | sub_objs = field.bulk_related_objects(new_objs, self.using) |
224 | 230 | self.collect(sub_objs, source=model, nullable=True) |
225 | 231 | |
| 232 | for error in self.protected_errors: |
| 233 | not_deleted = [obj for obj in error.protected_objects if obj not in self.data.get(obj.__class__, [])] |
| 234 | candidate_fast_deletes = [qs for qs in self.fast_deletes if qs.model == error.protected_objects[0].__class__] |
| 235 | |
| 236 | for obj in not_deleted: |
| 237 | if not any(qs.filter(pk=obj.pk).exists() for qs in candidate_fast_deletes): |
| 238 | raise error |
| 239 | |
226 | 240 | def related_objects(self, related, objs): |
227 | 241 | """ |
228 | 242 | Gets a QuerySet of objects related to ``objs`` via the relation ``related``. |