测试gitnore
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import operator
|
||||
from collections import Counter, defaultdict
|
||||
from functools import partial
|
||||
from functools import partial, reduce
|
||||
from itertools import chain
|
||||
from operator import attrgetter
|
||||
|
||||
@@ -21,11 +22,8 @@ class RestrictedError(IntegrityError):
|
||||
|
||||
def CASCADE(collector, field, sub_objs, using):
|
||||
collector.collect(
|
||||
sub_objs,
|
||||
source=field.remote_field.model,
|
||||
source_attr=field.name,
|
||||
nullable=field.null,
|
||||
fail_on_restricted=False,
|
||||
sub_objs, source=field.remote_field.model, source_attr=field.name,
|
||||
nullable=field.null, fail_on_restricted=False,
|
||||
)
|
||||
if field.null and not connections[using].features.can_defer_constraint_checks:
|
||||
collector.add_field_update(field, None, sub_objs)
|
||||
@@ -34,13 +32,10 @@ def CASCADE(collector, field, sub_objs, using):
|
||||
def PROTECT(collector, field, sub_objs, using):
|
||||
raise ProtectedError(
|
||||
"Cannot delete some instances of model '%s' because they are "
|
||||
"referenced through a protected foreign key: '%s.%s'"
|
||||
% (
|
||||
field.remote_field.model.__name__,
|
||||
sub_objs[0].__class__.__name__,
|
||||
field.name,
|
||||
"referenced through a protected foreign key: '%s.%s'" % (
|
||||
field.remote_field.model.__name__, sub_objs[0].__class__.__name__, field.name
|
||||
),
|
||||
sub_objs,
|
||||
sub_objs
|
||||
)
|
||||
|
||||
|
||||
@@ -51,16 +46,12 @@ def RESTRICT(collector, field, sub_objs, using):
|
||||
|
||||
def SET(value):
|
||||
if callable(value):
|
||||
|
||||
def set_on_delete(collector, field, sub_objs, using):
|
||||
collector.add_field_update(field, value(), sub_objs)
|
||||
|
||||
else:
|
||||
|
||||
def set_on_delete(collector, field, sub_objs, using):
|
||||
collector.add_field_update(field, value, sub_objs)
|
||||
|
||||
set_on_delete.deconstruct = lambda: ("django.db.models.SET", (value,), {})
|
||||
set_on_delete.deconstruct = lambda: ('django.db.models.SET', (value,), {})
|
||||
return set_on_delete
|
||||
|
||||
|
||||
@@ -80,8 +71,7 @@ def get_candidate_relations_to_delete(opts):
|
||||
# The candidate relations are the ones that come from N-1 and 1-1 relations.
|
||||
# N-N (i.e., many-to-many) relations aren't candidates for deletion.
|
||||
return (
|
||||
f
|
||||
for f in opts.get_fields(include_hidden=True)
|
||||
f for f in opts.get_fields(include_hidden=True)
|
||||
if f.auto_created and not f.concrete and (f.one_to_one or f.one_to_many)
|
||||
)
|
||||
|
||||
@@ -133,9 +123,7 @@ class Collector:
|
||||
def add_dependency(self, model, dependency, reverse_dependency=False):
|
||||
if reverse_dependency:
|
||||
model, dependency = dependency, model
|
||||
self.dependencies[model._meta.concrete_model].add(
|
||||
dependency._meta.concrete_model
|
||||
)
|
||||
self.dependencies[model._meta.concrete_model].add(dependency._meta.concrete_model)
|
||||
self.data.setdefault(dependency, self.data.default_factory())
|
||||
|
||||
def add_field_update(self, field, value, objs):
|
||||
@@ -162,21 +150,17 @@ class Collector:
|
||||
|
||||
def clear_restricted_objects_from_queryset(self, model, qs):
|
||||
if model in self.restricted_objects:
|
||||
objs = set(
|
||||
qs.filter(
|
||||
pk__in=[
|
||||
obj.pk
|
||||
for objs in self.restricted_objects[model].values()
|
||||
for obj in objs
|
||||
]
|
||||
)
|
||||
)
|
||||
objs = set(qs.filter(pk__in=[
|
||||
obj.pk
|
||||
for objs in self.restricted_objects[model].values() for obj in objs
|
||||
]))
|
||||
self.clear_restricted_objects_from_set(model, objs)
|
||||
|
||||
def _has_signal_listeners(self, model):
|
||||
return signals.pre_delete.has_listeners(
|
||||
model
|
||||
) or signals.post_delete.has_listeners(model)
|
||||
return (
|
||||
signals.pre_delete.has_listeners(model) or
|
||||
signals.post_delete.has_listeners(model)
|
||||
)
|
||||
|
||||
def can_fast_delete(self, objs, from_field=None):
|
||||
"""
|
||||
@@ -191,9 +175,9 @@ class Collector:
|
||||
"""
|
||||
if from_field and from_field.remote_field.on_delete is not CASCADE:
|
||||
return False
|
||||
if hasattr(objs, "_meta"):
|
||||
if hasattr(objs, '_meta'):
|
||||
model = objs._meta.model
|
||||
elif hasattr(objs, "model") and hasattr(objs, "_raw_delete"):
|
||||
elif hasattr(objs, 'model') and hasattr(objs, '_raw_delete'):
|
||||
model = objs.model
|
||||
else:
|
||||
return False
|
||||
@@ -203,22 +187,14 @@ class Collector:
|
||||
# parent when parent delete is cascading to child.
|
||||
opts = model._meta
|
||||
return (
|
||||
all(
|
||||
link == from_field
|
||||
for link in opts.concrete_model._meta.parents.values()
|
||||
)
|
||||
and
|
||||
all(link == from_field for link in opts.concrete_model._meta.parents.values()) and
|
||||
# Foreign keys pointing to this model.
|
||||
all(
|
||||
related.field.remote_field.on_delete is DO_NOTHING
|
||||
for related in get_candidate_relations_to_delete(opts)
|
||||
)
|
||||
and (
|
||||
) and (
|
||||
# Something like generic foreign key.
|
||||
not any(
|
||||
hasattr(field, "bulk_related_objects")
|
||||
for field in opts.private_fields
|
||||
)
|
||||
not any(hasattr(field, 'bulk_related_objects') for field in opts.private_fields)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -228,27 +204,16 @@ class Collector:
|
||||
"""
|
||||
field_names = [field.name for field in fields]
|
||||
conn_batch_size = max(
|
||||
connections[self.using].ops.bulk_batch_size(field_names, objs), 1
|
||||
)
|
||||
connections[self.using].ops.bulk_batch_size(field_names, objs), 1)
|
||||
if len(objs) > conn_batch_size:
|
||||
return [
|
||||
objs[i : i + conn_batch_size]
|
||||
for i in range(0, len(objs), conn_batch_size)
|
||||
]
|
||||
return [objs[i:i + conn_batch_size]
|
||||
for i in range(0, len(objs), conn_batch_size)]
|
||||
else:
|
||||
return [objs]
|
||||
|
||||
def collect(
|
||||
self,
|
||||
objs,
|
||||
source=None,
|
||||
nullable=False,
|
||||
collect_related=True,
|
||||
source_attr=None,
|
||||
reverse_dependency=False,
|
||||
keep_parents=False,
|
||||
fail_on_restricted=True,
|
||||
):
|
||||
def collect(self, objs, source=None, nullable=False, collect_related=True,
|
||||
source_attr=None, reverse_dependency=False, keep_parents=False,
|
||||
fail_on_restricted=True):
|
||||
"""
|
||||
Add 'objs' to the collection of objects to be deleted as well as all
|
||||
parent instances. 'objs' must be a homogeneous iterable collection of
|
||||
@@ -275,9 +240,8 @@ class Collector:
|
||||
if self.can_fast_delete(objs):
|
||||
self.fast_deletes.append(objs)
|
||||
return
|
||||
new_objs = self.add(
|
||||
objs, source, nullable, reverse_dependency=reverse_dependency
|
||||
)
|
||||
new_objs = self.add(objs, source, nullable,
|
||||
reverse_dependency=reverse_dependency)
|
||||
if not new_objs:
|
||||
return
|
||||
|
||||
@@ -290,14 +254,11 @@ class Collector:
|
||||
for ptr in concrete_model._meta.parents.values():
|
||||
if ptr:
|
||||
parent_objs = [getattr(obj, ptr.name) for obj in new_objs]
|
||||
self.collect(
|
||||
parent_objs,
|
||||
source=model,
|
||||
source_attr=ptr.remote_field.related_name,
|
||||
collect_related=False,
|
||||
reverse_dependency=True,
|
||||
fail_on_restricted=False,
|
||||
)
|
||||
self.collect(parent_objs, source=model,
|
||||
source_attr=ptr.remote_field.related_name,
|
||||
collect_related=False,
|
||||
reverse_dependency=True,
|
||||
fail_on_restricted=False)
|
||||
if not collect_related:
|
||||
return
|
||||
|
||||
@@ -325,18 +286,11 @@ class Collector:
|
||||
# relationships are select_related as interactions between both
|
||||
# features are hard to get right. This should only happen in
|
||||
# the rare cases where .related_objects is overridden anyway.
|
||||
if not (
|
||||
sub_objs.query.select_related
|
||||
or self._has_signal_listeners(related_model)
|
||||
):
|
||||
referenced_fields = set(
|
||||
chain.from_iterable(
|
||||
(rf.attname for rf in rel.field.foreign_related_fields)
|
||||
for rel in get_candidate_relations_to_delete(
|
||||
related_model._meta
|
||||
)
|
||||
)
|
||||
)
|
||||
if not (sub_objs.query.select_related or self._has_signal_listeners(related_model)):
|
||||
referenced_fields = set(chain.from_iterable(
|
||||
(rf.attname for rf in rel.field.foreign_related_fields)
|
||||
for rel in get_candidate_relations_to_delete(related_model._meta)
|
||||
))
|
||||
sub_objs = sub_objs.only(*tuple(referenced_fields))
|
||||
if sub_objs:
|
||||
try:
|
||||
@@ -346,11 +300,10 @@ class Collector:
|
||||
protected_objects[key] += error.protected_objects
|
||||
if protected_objects:
|
||||
raise ProtectedError(
|
||||
"Cannot delete some instances of model %r because they are "
|
||||
"referenced through protected foreign keys: %s."
|
||||
% (
|
||||
'Cannot delete some instances of model %r because they are '
|
||||
'referenced through protected foreign keys: %s.' % (
|
||||
model.__name__,
|
||||
", ".join(protected_objects),
|
||||
', '.join(protected_objects),
|
||||
),
|
||||
set(chain.from_iterable(protected_objects.values())),
|
||||
)
|
||||
@@ -360,12 +313,10 @@ class Collector:
|
||||
sub_objs = self.related_objects(related_model, related_fields, batch)
|
||||
self.fast_deletes.append(sub_objs)
|
||||
for field in model._meta.private_fields:
|
||||
if hasattr(field, "bulk_related_objects"):
|
||||
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, fail_on_restricted=False
|
||||
)
|
||||
self.collect(sub_objs, source=model, nullable=True, fail_on_restricted=False)
|
||||
|
||||
if fail_on_restricted:
|
||||
# Raise an error if collected restricted objects (RESTRICT) aren't
|
||||
@@ -383,12 +334,11 @@ class Collector:
|
||||
restricted_objects[key] += objs
|
||||
if restricted_objects:
|
||||
raise RestrictedError(
|
||||
"Cannot delete some instances of model %r because "
|
||||
"they are referenced through restricted foreign keys: "
|
||||
"%s."
|
||||
% (
|
||||
'Cannot delete some instances of model %r because '
|
||||
'they are referenced through restricted foreign keys: '
|
||||
'%s.' % (
|
||||
model.__name__,
|
||||
", ".join(restricted_objects),
|
||||
', '.join(restricted_objects),
|
||||
),
|
||||
set(chain.from_iterable(restricted_objects.values())),
|
||||
)
|
||||
@@ -397,10 +347,10 @@ class Collector:
|
||||
"""
|
||||
Get a QuerySet of the related model to objs via related fields.
|
||||
"""
|
||||
predicate = query_utils.Q(
|
||||
*((f"{related_field.name}__in", objs) for related_field in related_fields),
|
||||
_connector=query_utils.Q.OR,
|
||||
)
|
||||
predicate = reduce(operator.or_, (
|
||||
query_utils.Q(**{'%s__in' % related_field.name: objs})
|
||||
for related_field in related_fields
|
||||
))
|
||||
return related_model._base_manager.using(self.using).filter(predicate)
|
||||
|
||||
def instances_with_model(self):
|
||||
@@ -443,9 +393,7 @@ class Collector:
|
||||
instance = list(instances)[0]
|
||||
if self.can_fast_delete(instance):
|
||||
with transaction.mark_for_rollback_on_error(self.using):
|
||||
count = sql.DeleteQuery(model).delete_batch(
|
||||
[instance.pk], self.using
|
||||
)
|
||||
count = sql.DeleteQuery(model).delete_batch([instance.pk], self.using)
|
||||
setattr(instance, model._meta.pk.attname, None)
|
||||
return count, {model._meta.label: count}
|
||||
|
||||
@@ -467,9 +415,8 @@ class Collector:
|
||||
for model, instances_for_fieldvalues in self.field_updates.items():
|
||||
for (field, value), instances in instances_for_fieldvalues.items():
|
||||
query = sql.UpdateQuery(model)
|
||||
query.update_batch(
|
||||
[obj.pk for obj in instances], {field.name: value}, self.using
|
||||
)
|
||||
query.update_batch([obj.pk for obj in instances],
|
||||
{field.name: value}, self.using)
|
||||
|
||||
# reverse instance collections
|
||||
for instances in self.data.values():
|
||||
|
||||
Reference in New Issue
Block a user