slightly cleaner and more performant BaseQuerySet.delete
This commit is contained in:
parent
4e1145d890
commit
b99985eaf8
@ -383,7 +383,8 @@ class BaseQuerySet(object):
|
|||||||
return 0
|
return 0
|
||||||
return self._cursor.count(with_limit_and_skip=with_limit_and_skip)
|
return self._cursor.count(with_limit_and_skip=with_limit_and_skip)
|
||||||
|
|
||||||
def delete(self, write_concern=None, _from_doc_delete=False, cascade_refs=None):
|
def delete(self, write_concern=None, _from_doc_delete=False,
|
||||||
|
cascade_refs=None):
|
||||||
"""Delete the documents matched by the query.
|
"""Delete the documents matched by the query.
|
||||||
|
|
||||||
:param write_concern: Extra keyword arguments are passed down which
|
:param write_concern: Extra keyword arguments are passed down which
|
||||||
@ -406,8 +407,9 @@ class BaseQuerySet(object):
|
|||||||
# Handle deletes where skips or limits have been applied or
|
# Handle deletes where skips or limits have been applied or
|
||||||
# there is an untriggered delete signal
|
# there is an untriggered delete signal
|
||||||
has_delete_signal = signals.signals_available and (
|
has_delete_signal = signals.signals_available and (
|
||||||
signals.pre_delete.has_receivers_for(self._document) or
|
signals.pre_delete.has_receivers_for(doc) or
|
||||||
signals.post_delete.has_receivers_for(self._document))
|
signals.post_delete.has_receivers_for(doc)
|
||||||
|
)
|
||||||
|
|
||||||
call_document_delete = (queryset._skip or queryset._limit or
|
call_document_delete = (queryset._skip or queryset._limit or
|
||||||
has_delete_signal) and not _from_doc_delete
|
has_delete_signal) and not _from_doc_delete
|
||||||
@ -420,23 +422,29 @@ class BaseQuerySet(object):
|
|||||||
return cnt
|
return cnt
|
||||||
|
|
||||||
delete_rules = doc._meta.get('delete_rules') or {}
|
delete_rules = doc._meta.get('delete_rules') or {}
|
||||||
|
|
||||||
# Check for DENY rules before actually deleting/nullifying any other
|
# Check for DENY rules before actually deleting/nullifying any other
|
||||||
# references
|
# references
|
||||||
for rule_entry in delete_rules:
|
for rule_entry in delete_rules:
|
||||||
document_cls, field_name = rule_entry
|
document_cls, field_name = rule_entry
|
||||||
if document_cls._meta.get('abstract'):
|
if document_cls._meta.get('abstract'):
|
||||||
continue
|
continue
|
||||||
rule = doc._meta['delete_rules'][rule_entry]
|
|
||||||
if rule == DENY and document_cls.objects(
|
|
||||||
**{field_name + '__in': self}).count() > 0:
|
|
||||||
msg = ('Could not delete document (%s.%s refers to it)'
|
|
||||||
% (document_cls.__name__, field_name))
|
|
||||||
raise OperationError(msg)
|
|
||||||
|
|
||||||
|
rule = doc._meta['delete_rules'][rule_entry]
|
||||||
|
if rule == DENY:
|
||||||
|
refs = document_cls.objects(**{field_name + '__in': self})
|
||||||
|
if refs.limit(1).count() > 0:
|
||||||
|
raise OperationError(
|
||||||
|
'Could not delete document (%s.%s refers to it)'
|
||||||
|
% (document_cls.__name__, field_name)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check all the other rules
|
||||||
for rule_entry in delete_rules:
|
for rule_entry in delete_rules:
|
||||||
document_cls, field_name = rule_entry
|
document_cls, field_name = rule_entry
|
||||||
if document_cls._meta.get('abstract'):
|
if document_cls._meta.get('abstract'):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
rule = doc._meta['delete_rules'][rule_entry]
|
rule = doc._meta['delete_rules'][rule_entry]
|
||||||
if rule == CASCADE:
|
if rule == CASCADE:
|
||||||
cascade_refs = set() if cascade_refs is None else cascade_refs
|
cascade_refs = set() if cascade_refs is None else cascade_refs
|
||||||
@ -444,13 +452,15 @@ class BaseQuerySet(object):
|
|||||||
if doc._collection == document_cls._collection:
|
if doc._collection == document_cls._collection:
|
||||||
for ref in queryset:
|
for ref in queryset:
|
||||||
cascade_refs.add(ref.id)
|
cascade_refs.add(ref.id)
|
||||||
ref_q = document_cls.objects(**{field_name + '__in': self, 'pk__nin': cascade_refs})
|
refs = document_cls.objects(**{field_name + '__in': self,
|
||||||
ref_q_count = ref_q.count()
|
'pk__nin': cascade_refs})
|
||||||
if ref_q_count > 0:
|
if refs.count() > 0:
|
||||||
ref_q.delete(write_concern=write_concern, cascade_refs=cascade_refs)
|
refs.delete(write_concern=write_concern,
|
||||||
|
cascade_refs=cascade_refs)
|
||||||
elif rule == NULLIFY:
|
elif rule == NULLIFY:
|
||||||
document_cls.objects(**{field_name + '__in': self}).update(
|
document_cls.objects(**{field_name + '__in': self}).update(
|
||||||
write_concern=write_concern, **{'unset__%s' % field_name: 1})
|
write_concern=write_concern,
|
||||||
|
**{'unset__%s' % field_name: 1})
|
||||||
elif rule == PULL:
|
elif rule == PULL:
|
||||||
document_cls.objects(**{field_name + '__in': self}).update(
|
document_cls.objects(**{field_name + '__in': self}).update(
|
||||||
write_concern=write_concern,
|
write_concern=write_concern,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user