From 6471c6e133cbca62983b3f785191457732daa3c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wilson=20J=C3=BAnior?= Date: Wed, 27 Jul 2011 08:45:15 -0300 Subject: [PATCH] added GenericEmbeddedDocumentField --- mongoengine/fields.py | 28 +++++++++++++++++++++++++++- tests/fields.py | 25 +++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/mongoengine/fields.py b/mongoengine/fields.py index b2f1e2a2..7d57d78f 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -21,7 +21,7 @@ __all__ = ['StringField', 'IntField', 'FloatField', 'BooleanField', 'DecimalField', 'ComplexDateTimeField', 'URLField', 'GenericReferenceField', 'FileField', 'BinaryField', 'SortedListField', 'EmailField', 'GeoPointField', - 'SequenceField'] + 'SequenceField', 'GenericEmbeddedDocumentField'] RECURSIVE_REFERENCE_CONSTANT = 'self' @@ -420,6 +420,32 @@ class EmbeddedDocumentField(BaseField): def prepare_query_value(self, op, value): return self.to_mongo(value) +class GenericEmbeddedDocumentField(BaseField): + def prepare_query_value(self, op, value): + return self.to_mongo(value) + + def to_python(self, value): + if isinstance(value, dict): + doc_cls = get_document(value['_cls']) + value = doc_cls._from_son(value) + + return value + + def validate(self, value): + if not isinstance(value, EmbeddedDocument): + raise ValidationError('Invalid embedded document instance ' + 'provided to an GenericEmbeddedDocumentField') + + value.validate() + + def to_mongo(self, document): + if document is None: + return None + + data = document.to_mongo() + if not '_cls' in data: + data['_cls'] = document._class_name + return data class ListField(ComplexBaseField): """A list field that wraps a standard field, allowing multiple instances diff --git a/tests/fields.py b/tests/fields.py index f8aeb86c..960e55c9 100644 --- a/tests/fields.py +++ b/tests/fields.py @@ -1488,5 +1488,30 @@ class FieldTest(unittest.TestCase): self.assertEqual(c['next'], 10) + def test_generic_embedded_document(self): + class Car(EmbeddedDocument): + name = StringField() + + class Dish(EmbeddedDocument): + food = StringField(required=True) + number = IntField() + + class Person(Document): + name = StringField() + like = GenericEmbeddedDocumentField() + + person = Person(name='Test User') + person.like = Car(name='Fiat') + person.save() + + person = Person.objects.first() + self.assertTrue(isinstance(person.like, Car)) + + person.like = Dish(food="arroz", number=15) + person.save() + + person = Person.objects.first() + self.assertTrue(isinstance(person.like, Dish)) + if __name__ == '__main__': unittest.main()