From f9ccf635ca17e7f30efaeccba37b32c7ea062157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20W=C3=B3jcik?= Date: Sun, 5 Mar 2017 18:20:09 -0500 Subject: [PATCH] Respect db fields in multiple layers of embedded docs (#1501) --- mongoengine/base/document.py | 9 ++++++-- tests/fields/fields.py | 45 ++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/mongoengine/base/document.py b/mongoengine/base/document.py index 9d366706..ce96837a 100644 --- a/mongoengine/base/document.py +++ b/mongoengine/base/document.py @@ -684,8 +684,13 @@ class BaseDocument(object): # class if unavailable class_name = son.get('_cls', cls._class_name) - # Convert SON to a dict, making sure each key is a string - data = {str(key): value for key, value in son.iteritems()} + # Convert SON to a data dict, making sure each key is a string and + # corresponds to the right db field. + data = {} + for key, value in son.iteritems(): + key = str(key) + key = cls._db_field_map.get(key, key) + data[key] = value # Return correct subclass for document type if class_name != cls._class_name: diff --git a/tests/fields/fields.py b/tests/fields/fields.py index 8e0da410..2305f3af 100644 --- a/tests/fields/fields.py +++ b/tests/fields/fields.py @@ -1901,6 +1901,51 @@ class FieldTest(MongoDBTestCase): doc = self.db.test.find_one() self.assertEqual(doc['x']['i'], 2) + def test_double_embedded_db_field(self): + """Make sure multiple layers of embedded docs resolve db fields + properly and can be initialized using dicts. + """ + class C(EmbeddedDocument): + txt = StringField() + + class B(EmbeddedDocument): + c = EmbeddedDocumentField(C, db_field='fc') + + class A(Document): + b = EmbeddedDocumentField(B, db_field='fb') + + a = A( + b=B( + c=C(txt='hi') + ) + ) + a.validate() + + a = A(b={'c': {'txt': 'hi'}}) + a.validate() + + def test_double_embedded_db_field_from_son(self): + """Make sure multiple layers of embedded docs resolve db fields + from SON properly. + """ + class C(EmbeddedDocument): + txt = StringField() + + class B(EmbeddedDocument): + c = EmbeddedDocumentField(C, db_field='fc') + + class A(Document): + b = EmbeddedDocumentField(B, db_field='fb') + + a = A._from_son(SON([ + ('fb', SON([ + ('fc', SON([ + ('txt', 'hi') + ])) + ])) + ])) + self.assertEqual(a.b.c.txt, 'hi') + def test_embedded_document_validation(self): """Ensure that invalid embedded documents cannot be assigned to embedded document fields.