Made Collector.collect() return immediately for disabled related collection.

This commit is contained in:
Simon Charette 2019-10-06 21:48:14 +02:00 committed by Mariusz Felisiak
parent 832aa08afe
commit 44522d1036
1 changed files with 40 additions and 37 deletions

View File

@ -210,43 +210,46 @@ class Collector:
source_attr=ptr.remote_field.related_name, source_attr=ptr.remote_field.related_name,
collect_related=False, collect_related=False,
reverse_dependency=True) reverse_dependency=True)
if collect_related: if not collect_related:
if keep_parents: return
parents = set(model._meta.get_parent_list())
for related in get_candidate_relations_to_delete(model._meta): if keep_parents:
# Preserve parent reverse relationships if keep_parents=True. parents = set(model._meta.get_parent_list())
if keep_parents and related.model in parents: for related in get_candidate_relations_to_delete(model._meta):
continue # Preserve parent reverse relationships if keep_parents=True.
field = related.field if keep_parents and related.model in parents:
if field.remote_field.on_delete == DO_NOTHING: continue
continue field = related.field
batches = self.get_del_batches(new_objs, field) if field.remote_field.on_delete == DO_NOTHING:
for batch in batches: continue
sub_objs = self.related_objects(related, batch) batches = self.get_del_batches(new_objs, field)
if self.can_fast_delete(sub_objs, from_field=field): for batch in batches:
self.fast_deletes.append(sub_objs) sub_objs = self.related_objects(related, batch)
else: if self.can_fast_delete(sub_objs, from_field=field):
related_model = related.related_model self.fast_deletes.append(sub_objs)
# Non-referenced fields can be deferred if no signal else:
# receivers are connected for the related model as related_model = related.related_model
# they'll never be exposed to the user. Skip field # Non-referenced fields can be deferred if no signal
# deferring when some relationships are select_related # receivers are connected for the related model as
# as interactions between both features are hard to # they'll never be exposed to the user. Skip field
# get right. This should only happen in the rare # deferring when some relationships are select_related
# cases where .related_objects is overridden anyway. # as interactions between both features are hard to
if not (sub_objs.query.select_related or self._has_signal_listeners(related_model)): # get right. This should only happen in the rare
referenced_fields = set(chain.from_iterable( # cases where .related_objects is overridden anyway.
(rf.attname for rf in rel.field.foreign_related_fields) if not (sub_objs.query.select_related or self._has_signal_listeners(related_model)):
for rel in get_candidate_relations_to_delete(related_model._meta) referenced_fields = set(chain.from_iterable(
)) (rf.attname for rf in rel.field.foreign_related_fields)
sub_objs = sub_objs.only(*tuple(referenced_fields)) for rel in get_candidate_relations_to_delete(related_model._meta)
if sub_objs: ))
field.remote_field.on_delete(self, field, sub_objs, self.using) sub_objs = sub_objs.only(*tuple(referenced_fields))
for field in model._meta.private_fields: if sub_objs:
if hasattr(field, 'bulk_related_objects'): field.remote_field.on_delete(self, field, sub_objs, self.using)
# It's something like generic foreign key.
sub_objs = field.bulk_related_objects(new_objs, self.using) for field in model._meta.private_fields:
self.collect(sub_objs, source=model, nullable=True) if hasattr(field, 'bulk_related_objects'):
# It's something like generic foreign key.
sub_objs = field.bulk_related_objects(new_objs, self.using)
self.collect(sub_objs, source=model, nullable=True)
def related_objects(self, related, objs): def related_objects(self, related, objs):
""" """