Merge pull request #1 from emilecaron/fix_delete_rule_cascade_cycle
Fix delete rule cascade cycle
This commit is contained in:
commit
13e0a1b5bb
@ -346,7 +346,7 @@ class BaseQuerySet(object):
|
||||
return 0
|
||||
return self._cursor.count(with_limit_and_skip=with_limit_and_skip)
|
||||
|
||||
def delete(self, write_concern=None, _from_doc_delete=False):
|
||||
def delete(self, write_concern=None, _from_doc_delete=False, cascade_refs=None):
|
||||
"""Delete the documents matched by the query.
|
||||
|
||||
:param write_concern: Extra keyword arguments are passed down which
|
||||
@ -363,6 +363,11 @@ class BaseQuerySet(object):
|
||||
queryset = self.clone()
|
||||
doc = queryset._document
|
||||
|
||||
cascade_refs = set() if cascade_refs is None else cascade_refs
|
||||
if doc in cascade_refs:
|
||||
return 0
|
||||
cascade_refs.add(doc)
|
||||
|
||||
if write_concern is None:
|
||||
write_concern = {}
|
||||
|
||||
@ -404,9 +409,8 @@ class BaseQuerySet(object):
|
||||
if rule == CASCADE:
|
||||
ref_q = document_cls.objects(**{field_name + '__in': self})
|
||||
ref_q_count = ref_q.count()
|
||||
if (doc != document_cls and ref_q_count > 0 or
|
||||
(doc == document_cls and ref_q_count > 0)):
|
||||
ref_q.delete(write_concern=write_concern)
|
||||
if ref_q_count > 0:
|
||||
ref_q.delete(write_concern=write_concern, cascade_refs=cascade_refs)
|
||||
elif rule == NULLIFY:
|
||||
document_cls.objects(**{field_name + '__in': self}).update(
|
||||
write_concern=write_concern, **{'unset__%s' % field_name: 1})
|
||||
|
@ -1413,6 +1413,23 @@ class QuerySetTest(unittest.TestCase):
|
||||
self.Person.objects(name='Test User').delete()
|
||||
self.assertEqual(1, BlogPost.objects.count())
|
||||
|
||||
def test_reverse_delete_rule_cascade_cycle(self):
|
||||
"""Ensure reference cascading doesn't loop if reference graph isn't
|
||||
a tree
|
||||
"""
|
||||
class Dummy(Document):
|
||||
reference = ReferenceField('self', reverse_delete_rule=CASCADE)
|
||||
|
||||
base = Dummy().save()
|
||||
other = Dummy(reference=base).save()
|
||||
base.reference = other
|
||||
base.save()
|
||||
|
||||
base.delete()
|
||||
|
||||
self.assertRaises(DoesNotExist, base.reload)
|
||||
self.assertRaises(DoesNotExist, other.reload)
|
||||
|
||||
def test_reverse_delete_rule_cascade_self_referencing(self):
|
||||
"""Ensure self-referencing CASCADE deletes do not result in infinite
|
||||
loop
|
||||
|
Loading…
x
Reference in New Issue
Block a user