这是使用 EmbeddedDocuments 更新文档的功能。它基于@rednaw 的解决方案,但考虑了具有 EmbeddedDocuments 的 EmbeddedDocuments。
from mongoengine.fields import *
def field_value(field, value):
'''
Converts a supplied value to the type required by the field.
If the field requires a EmbeddedDocument the EmbeddedDocument
is created and updated using the supplied data.
'''
if field.__class__ in (ListField, SortedListField):
# return a list of the field values
return [
field_value(field.field, item)
for item in value]
elif field.__class__ in (
EmbeddedDocumentField,
GenericEmbeddedDocumentField,
ReferenceField,
GenericReferenceField):
embedded_doc = field.document_type()
update_document(embedded_doc, value)
return embedded_doc
else:
return value
def update_document(doc, data):
''' Update an document to match the supplied dictionary.
'''
for key, value in data.iteritems():
if hasattr(doc, key):
value = field_value(doc._fields[key], value)
setattr(doc, key, value)
else:
# handle invalid key
pass
return doc
这里的关键是field_value
更新嵌入文档的方法,而不是用数据实例化它。
用法示例:
class Pets(EmbeddedDocument):
name = StringField()
class Person(EmbeddedDocument):
name = StringField()
address = StringField()
pets = ListField(EmbeddedDocumentField(Pets))
class Group(Document):
name = StringField()
members = ListField(EmbeddedDocumentField(Person))
g = Group()
update_document(g, {
'name': 'Coding Buddies',
'members': [
{
'name': 'Dawson',
'address': 'Somewhere in Nova Scotia',
'pets': [
{
'name': 'Sparkles'
}
]
},
{
'name': 'rednaw',
'address': 'Not too sure?',
'pets': [
{
'name': 'Fluffy'
}
]
}
]
})
仅供参考,这实际上是我猫的名字。
编辑:变量名中的错字。