From dd21ce9eac4156936f17e7106c1b048fe6069015 Mon Sep 17 00:00:00 2001 From: Vincent Driessen Date: Sun, 5 Dec 2010 13:40:39 -0800 Subject: [PATCH] Initial implementation of the NULLIFY rule. --- mongoengine/document.py | 13 +++++++++++++ tests/document.py | 11 ++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/mongoengine/document.py b/mongoengine/document.py index 06867168..3b812abb 100644 --- a/mongoengine/document.py +++ b/mongoengine/document.py @@ -105,6 +105,19 @@ class Document(BaseDocument): if rule == CASCADE: document_cls.objects(**{field_name: self.id}).delete(safe=safe) + elif rule == NULLIFY: + # TODO: For now, this makes the nullify test pass, but it would + # be nicer to use any of these two atomic versions: + # + # document_cls.objects(**{field_name: self.id}).update(**{'unset__%s' % field_name: 1}) + # or + # document_cls.objects(**{field_name: self.id}).update(**{'set__%s' % field_name: None}) + # + # However, I'm getting ValidationError: 1/None is not a valid ObjectId + # Anybody got a clue? + for doc in document_cls.objects(**{field_name: self.id}): + doc.reviewer = None + doc.save() id_field = self._meta['id_field'] object_id = self._fields[id_field].to_mongo(self[id_field]) diff --git a/tests/document.py b/tests/document.py index d5807c90..7f92320d 100644 --- a/tests/document.py +++ b/tests/document.py @@ -625,7 +625,7 @@ class DocumentTest(unittest.TestCase): BlogPost.drop_collection() - def test_cascade_delete(self): + def test_delete_rule_cascade_and_nullify(self): """Ensure that a referenced document is also deleted upon deletion. """ @@ -633,6 +633,7 @@ class DocumentTest(unittest.TestCase): meta = {'collection': 'blogpost_1'} content = StringField() author = ReferenceField(self.Person, delete_rule=CASCADE) + reviewer = ReferenceField(self.Person, delete_rule=NULLIFY) self.Person.drop_collection() BlogPost.drop_collection() @@ -640,10 +641,18 @@ class DocumentTest(unittest.TestCase): author = self.Person(name='Test User') author.save() + reviewer = self.Person(name='Re Viewer') + reviewer.save() + post = BlogPost(content = 'Watched some TV') post.author = author + post.reviewer = reviewer post.save() + reviewer.delete() + self.assertEqual(len(BlogPost.objects), 1) # No effect on the BlogPost + self.assertEqual(BlogPost.objects.get().reviewer, None) + # Delete the Person, which should lead to deletion of the BlogPost, too author.delete() self.assertEqual(len(BlogPost.objects), 0)