Added initial implementation of cascading document deletion.

The current implementation is still very basic and needs some polish.
The essence of it is that each Document gets a new meta attribute called
"delete_rules" that is a dictionary containing (documentclass,
fieldname) as key and the actual delete rule as a value.  (Possible
values are DO_NOTHING, NULLIFY, CASCADE and DENY.  Of those, only
CASCADE is currently implented.)
This commit is contained in:
Vincent Driessen
2010-12-05 08:08:55 -08:00
parent 4f3eacd72c
commit 86233bcdf5
4 changed files with 56 additions and 2 deletions

View File

@@ -6,9 +6,16 @@ from connection import _get_db
import pymongo
__all__ = ['Document', 'EmbeddedDocument', 'ValidationError', 'OperationError']
__all__ = ['Document', 'EmbeddedDocument', 'ValidationError', 'OperationError',
'DO_NOTHING', 'NULLIFY', 'CASCADE', 'DENY']
# Delete rules
DO_NOTHING = 0
NULLIFY = 1
CASCADE = 2
DENY = 3
class EmbeddedDocument(BaseDocument):
"""A :class:`~mongoengine.Document` that isn't stored in its own
collection. :class:`~mongoengine.EmbeddedDocument`\ s should be used as
@@ -92,6 +99,13 @@ class Document(BaseDocument):
:param safe: check if the operation succeeded before returning
"""
for rule_entry in self._meta['delete_rules']:
document_cls, field_name = rule_entry
rule = self._meta['delete_rules'][rule_entry]
if rule == CASCADE:
document_cls.objects(**{field_name: self.id}).delete(safe=safe)
id_field = self._meta['id_field']
object_id = self._fields[id_field].to_mongo(self[id_field])
try:
@@ -100,6 +114,17 @@ class Document(BaseDocument):
message = u'Could not delete document (%s)' % err.message
raise OperationError(message)
@classmethod
def register_delete_rule(cls, document_cls, field_name, rule):
"""This method registers the delete rules to apply when removing this
object. This could go into the Document class.
"""
if rule == DO_NOTHING:
return
cls._meta['delete_rules'][(document_cls, field_name)] = rule
def reload(self):
"""Reloads all attributes from the database.