Skip to content

Commit f9ccf63

Browse files
authored
Respect db fields in multiple layers of embedded docs (#1501)
1 parent e8ea294 commit f9ccf63

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

mongoengine/base/document.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -684,8 +684,13 @@ def _from_son(cls, son, _auto_dereference=True, only_fields=None, created=False)
684684
# class if unavailable
685685
class_name = son.get('_cls', cls._class_name)
686686

687-
# Convert SON to a dict, making sure each key is a string
688-
data = {str(key): value for key, value in son.iteritems()}
687+
# Convert SON to a data dict, making sure each key is a string and
688+
# corresponds to the right db field.
689+
data = {}
690+
for key, value in son.iteritems():
691+
key = str(key)
692+
key = cls._db_field_map.get(key, key)
693+
data[key] = value
689694

690695
# Return correct subclass for document type
691696
if class_name != cls._class_name:

tests/fields/fields.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1901,6 +1901,51 @@ class Test(Document):
19011901
doc = self.db.test.find_one()
19021902
self.assertEqual(doc['x']['i'], 2)
19031903

1904+
def test_double_embedded_db_field(self):
1905+
"""Make sure multiple layers of embedded docs resolve db fields
1906+
properly and can be initialized using dicts.
1907+
"""
1908+
class C(EmbeddedDocument):
1909+
txt = StringField()
1910+
1911+
class B(EmbeddedDocument):
1912+
c = EmbeddedDocumentField(C, db_field='fc')
1913+
1914+
class A(Document):
1915+
b = EmbeddedDocumentField(B, db_field='fb')
1916+
1917+
a = A(
1918+
b=B(
1919+
c=C(txt='hi')
1920+
)
1921+
)
1922+
a.validate()
1923+
1924+
a = A(b={'c': {'txt': 'hi'}})
1925+
a.validate()
1926+
1927+
def test_double_embedded_db_field_from_son(self):
1928+
"""Make sure multiple layers of embedded docs resolve db fields
1929+
from SON properly.
1930+
"""
1931+
class C(EmbeddedDocument):
1932+
txt = StringField()
1933+
1934+
class B(EmbeddedDocument):
1935+
c = EmbeddedDocumentField(C, db_field='fc')
1936+
1937+
class A(Document):
1938+
b = EmbeddedDocumentField(B, db_field='fb')
1939+
1940+
a = A._from_son(SON([
1941+
('fb', SON([
1942+
('fc', SON([
1943+
('txt', 'hi')
1944+
]))
1945+
]))
1946+
]))
1947+
self.assertEqual(a.b.c.txt, 'hi')
1948+
19041949
def test_embedded_document_validation(self):
19051950
"""Ensure that invalid embedded documents cannot be assigned to
19061951
embedded document fields.

0 commit comments

Comments
 (0)