105 | | if obj not in instances: |
106 | | new_objs.append(obj) |
107 | | instances.update(new_objs) |
108 | | # Nullable relationships can be ignored -- they are nulled out before |
109 | | # deleting, and therefore do not affect the order in which objects have |
110 | | # to be deleted. |
111 | | if source is not None and not nullable: |
112 | | if reverse_dependency: |
113 | | source, model = model, source |
114 | | self.dependencies.setdefault( |
115 | | source._meta.concrete_model, set()).add(model._meta.concrete_model) |
| 109 | model = obj.__class__ |
| 110 | concrete_model = model._meta.concrete_model |
| 111 | concrete_model_objs.setdefault(concrete_model, {}) |
| 112 | concrete_model_objs[concrete_model].setdefault(model, []) |
| 113 | concrete_model_objs[concrete_model][model].append(obj) |
| 114 | |
| 115 | for concrete_model, model_objs in concrete_model_objs.iteritems(): |
| 116 | for model, objs in model_objs.iteritems(): |
| 117 | instances = self.data.setdefault(model, set()) |
| 118 | for obj in objs: |
| 119 | if obj not in instances: |
| 120 | new_objs.append(obj) |
| 121 | instances.update(new_objs) |
| 122 | # Nullable relationships can be ignored -- they are nulled out before |
| 123 | # deleting, and therefore do not affect the order in which objects have |
| 124 | # to be deleted. |
| 125 | if source is not None and not nullable: |
| 126 | if reverse_dependency: |
| 127 | source_, concrete_model_ = concrete_model, source |
| 128 | else: |
| 129 | concrete_model_, source_ = concrete_model, source |
| 130 | self.dependencies.setdefault( |
| 131 | source_, set()).add(concrete_model_) |
132 | | model = objs[0].__class__ |
133 | | self.field_updates.setdefault( |
134 | | model, {}).setdefault( |
135 | | (field, value), set()).update(objs) |
| 148 | |
| 149 | concrete_model_objs = {} |
| 150 | for obj in objs: |
| 151 | model = obj.__class__ |
| 152 | concrete_model = model._meta.concrete_model |
| 153 | concrete_model_objs.setdefault(concrete_model, {}) |
| 154 | concrete_model_objs[concrete_model].setdefault(model, []) |
| 155 | concrete_model_objs[concrete_model][model].append(obj) |
| 156 | |
| 157 | for concrete_model, model_objs in concrete_model_objs.iteritems(): |
| 158 | for model, objs in model_objs.iteritems(): |
| 159 | self.field_updates.setdefault( |
| 160 | model, {}).setdefault( |
| 161 | (field, value), set()).update(objs) |
199 | | model = new_objs[0].__class__ |
200 | | |
201 | | # Recursively collect concrete model's parent models, but not their |
202 | | # related objects. These will be found by meta.get_all_related_objects() |
203 | | concrete_model = model._meta.concrete_model |
204 | | for ptr in six.itervalues(concrete_model._meta.parents): |
205 | | if ptr: |
206 | | # FIXME: This seems to be buggy and execute a query for each |
207 | | # parent object fetch. We have the parent data in the obj, |
208 | | # but we don't have a nice way to turn that data into parent |
209 | | # object instance. |
210 | | parent_objs = [getattr(obj, ptr.name) for obj in new_objs] |
| 225 | concrete_model_objs = {} |
| 226 | for obj in new_objs: |
| 227 | model = obj.__class__ |
| 228 | concrete_model = model._meta.concrete_model |
| 229 | concrete_model_objs.setdefault(concrete_model, {}) |
| 230 | concrete_model_objs[concrete_model].setdefault(model, []) |
| 231 | concrete_model_objs[concrete_model][model].append(obj) |
| 232 | |
| 233 | for concrete_model, model_objs in concrete_model_objs.iteritems(): |
| 234 | parent_objs = [] |
| 235 | for model, new_objs in model_objs.iteritems(): |
| 236 | # Recursively collect concrete model's parent models, but not their |
| 237 | # related objects. These will be found by meta.get_all_related_objects() |
| 238 | for ptr in six.itervalues(concrete_model._meta.parents): |
| 239 | if ptr: |
| 240 | # FIXME: This seems to be buggy and execute a query for each |
| 241 | # parent object fetch. We have the parent data in the obj, |
| 242 | # but we don't have a nice way to turn that data into parent |
| 243 | # object instance. |
| 244 | parent_objs += [getattr(obj, ptr.name) for obj in new_objs] |
| 245 | if parent_objs: |
216 | | if collect_related: |
217 | | for related in model._meta.get_all_related_objects( |
218 | | include_hidden=True, include_proxy_eq=True): |
219 | | field = related.field |
220 | | if field.rel.on_delete == DO_NOTHING: |
221 | | continue |
222 | | sub_objs = self.related_objects(related, new_objs) |
223 | | if self.can_fast_delete(sub_objs, from_field=field): |
224 | | self.fast_deletes.append(sub_objs) |
225 | | elif sub_objs: |
226 | | field.rel.on_delete(self, field, sub_objs, self.using) |
227 | | |
228 | | # TODO This entire block is only needed as a special case to |
229 | | # support cascade-deletes for GenericRelation. It should be |
230 | | # removed/fixed when the ORM gains a proper abstraction for virtual |
231 | | # or composite fields, and GFKs are reworked to fit into that. |
232 | | for relation in model._meta.many_to_many: |
233 | | if not relation.rel.through: |
234 | | sub_objs = relation.bulk_related_objects(new_objs, self.using) |
235 | | self.collect(sub_objs, |
236 | | source=model, |
237 | | source_attr=relation.rel.related_name, |
238 | | nullable=True) |
| 251 | if collect_related: |
| 252 | for model, new_objs in model_objs.iteritems(): |
| 253 | for related in model._meta.get_all_related_objects( |
| 254 | include_hidden=True, include_proxy_eq=True): |
| 255 | field = related.field |
| 256 | if field.rel.on_delete == DO_NOTHING: |
| 257 | continue |
| 258 | sub_objs = self.related_objects(related, new_objs) |
| 259 | if self.can_fast_delete(sub_objs, from_field=field): |
| 260 | self.fast_deletes.append(sub_objs) |
| 261 | elif sub_objs: |
| 262 | field.rel.on_delete(self, field, sub_objs, self.using) |
| 263 | |
| 264 | # TODO This entire block is only needed as a special case to |
| 265 | # support cascade-deletes for GenericRelation. It should be |
| 266 | # removed/fixed when the ORM gains a proper abstraction for virtual |
| 267 | # or composite fields, and GFKs are reworked to fit into that. |
| 268 | for relation in model._meta.many_to_many: |
| 269 | if not relation.rel.through: |
| 270 | sub_objs = relation.bulk_related_objects(new_objs, self.using) |
| 271 | self.collect(sub_objs, |
| 272 | source=model, |
| 273 | source_attr=relation.rel.related_name, |
| 274 | nullable=True) |