| 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) |