Added Reverse Delete Rule support to ListFields
DictFields and MapFields aren't supported and raise an InvalidDocument Error Closes #254
This commit is contained in:
parent
9188f9bf62
commit
8a44232bfc
@ -503,15 +503,22 @@ class DocumentMetaclass(type):
|
||||
attrs['_db_field_map'] = dict([(k, v.db_field) for k, v in doc_fields.items() if k!=v.db_field])
|
||||
attrs['_reverse_db_field_map'] = dict([(v, k) for k, v in attrs['_db_field_map'].items()])
|
||||
|
||||
from mongoengine import Document, EmbeddedDocument
|
||||
from mongoengine import Document, EmbeddedDocument, DictField
|
||||
|
||||
new_class = super_new(cls, name, bases, attrs)
|
||||
for field in new_class._fields.values():
|
||||
field.owner_document = new_class
|
||||
|
||||
delete_rule = getattr(field, 'reverse_delete_rule', DO_NOTHING)
|
||||
f = field
|
||||
if isinstance(f, ComplexBaseField) and hasattr(f, 'field'):
|
||||
delete_rule = getattr(f.field, 'reverse_delete_rule', DO_NOTHING)
|
||||
if isinstance(f, DictField) and delete_rule != DO_NOTHING:
|
||||
raise InvalidDocumentError("Reverse delete rules are not supported for %s (field: %s)" % (field.__class__.__name__, field.name))
|
||||
f = field.field
|
||||
|
||||
if delete_rule != DO_NOTHING:
|
||||
field.document_type.register_delete_rule(new_class, field.name,
|
||||
delete_rule)
|
||||
f.document_type.register_delete_rule(new_class, field.name, delete_rule)
|
||||
|
||||
if field.name and hasattr(Document, field.name) and EmbeddedDocument not in new_class.mro():
|
||||
raise InvalidDocumentError("%s is a document method and not a valid field name" % field.name)
|
||||
|
@ -2214,6 +2214,46 @@ class DocumentTest(unittest.TestCase):
|
||||
author.delete()
|
||||
self.assertEqual(len(BlogPost.objects), 0)
|
||||
|
||||
def test_reverse_delete_rule_cascade_and_nullify_complex_field(self):
|
||||
"""Ensure that a referenced document is also deleted upon deletion.
|
||||
"""
|
||||
|
||||
class BlogPost(Document):
|
||||
content = StringField()
|
||||
authors = ListField(ReferenceField(self.Person, reverse_delete_rule=CASCADE))
|
||||
reviewers = ListField(ReferenceField(self.Person, reverse_delete_rule=NULLIFY))
|
||||
|
||||
self.Person.drop_collection()
|
||||
BlogPost.drop_collection()
|
||||
|
||||
author = self.Person(name='Test User')
|
||||
author.save()
|
||||
|
||||
reviewer = self.Person(name='Re Viewer')
|
||||
reviewer.save()
|
||||
|
||||
post = BlogPost(content= 'Watched some TV')
|
||||
post.authors = [author]
|
||||
post.reviewers = [reviewer]
|
||||
post.save()
|
||||
|
||||
reviewer.delete()
|
||||
self.assertEqual(len(BlogPost.objects), 1) # No effect on the BlogPost
|
||||
self.assertEqual(BlogPost.objects.get().reviewers, [])
|
||||
|
||||
# Delete the Person, which should lead to deletion of the BlogPost, too
|
||||
author.delete()
|
||||
self.assertEqual(len(BlogPost.objects), 0)
|
||||
|
||||
def throw_invalid_document_error():
|
||||
class Blog(Document):
|
||||
content = StringField()
|
||||
authors = MapField(ReferenceField(self.Person, reverse_delete_rule=CASCADE))
|
||||
reviewers = DictField(field=ReferenceField(self.Person, reverse_delete_rule=NULLIFY))
|
||||
|
||||
self.assertRaises(InvalidDocumentError, throw_invalid_document_error)
|
||||
|
||||
|
||||
def test_reverse_delete_rule_cascade_recurs(self):
|
||||
"""Ensure that a chain of documents is also deleted upon cascaded
|
||||
deletion.
|
||||
|
Loading…
x
Reference in New Issue
Block a user