首页 > 解决方案 > Mongoengine EmbeddedDocumentListField // 我只能访问get方法

问题描述

我正在为我的学校创建一个数据库。有一个学生文档,其中包含成人的 EmbeddedDocumentListField。我正在尝试使用 EmbeddedDocumentListField 方法更新现有的 EmbeddedDocuments,但 save() 和 update() 都会给我错误。get() 似乎工作。

class Adult(EmbeddedDocument):
    relation = StringField() # Adult, Mother, Father, Grandmother...
    ...
    notes = StringField()

class Student(Document):
    afname = StringField()
    alname = StringField()
    ...
    adults = EmbeddedDocumentListField('Adult')

我能够成功使用 get 方法

@app.route('/editadult/<aeriesid>/<adultoid>')
def editadult(aeriesid,adultoid):
    editUser = User.objects.get(aeriesid=aeriesid)
    editAdult = editUser.adults.get(oid=adultoid)

这将返回名为 editAdult 的对象,该对象具有预期的属性,但没有方法。我现在想更新该对象中的值。我可以通过做来查看我想要调用的方法。

dir(editUser.adults)

但看不到方法

dir(editAdult)

根据我对文档的阅读,我应该能够做到这一点。

editAdult.update(fname="Juanita", lname="Sanchez")

这给出了错误:AttributeError:“成人”对象没有属性“更新”。但无法弄清楚如何在该上下文中使用这些方法。我试过了

editAdult.fname = "Juanita"
editAdult.lname = "Sanchez"
editAdult.save()

但这给出了错误: AttributeError: 'Adult' object has no attribute 'save'

文档很少。Mongoengine 告诉我这些方法是什么,但没有示例。 http://docs.mongoengine.org/apireference.html#embedded-document-querying GitHub 提供了很好的示例,但我无法让它们工作。 https://github.com/MongoEngine/mongoengine/pull/826

我正在使用 Mongoengine 0.20.0

标签: flaskmongoengine

解决方案


经过大量的试验和错误,我想通了。使用此数据结构:

class Adult(EmbeddedDocument):
    relation = StringField() # Adult, Mother, Father, Grandmother...
    fname = StringField()
    lname = StringField()
    ...
    notes = StringField()

class Student(Document):
    afname = StringField()
    alname = StringField()
    ...
    adults = EmbeddedDocumentListField('Adult')

然后我创建了这个 Flask Route

@app.route('/editadult/<aeriesid>/<adultoid>')
def editadult(aeriesid,adultoid):
    editUser = User.objects.get(aeriesid=aeriesid)
    editAdult = editUser.adults.get(oid=adultoid)

Adultoid 是成人的唯一标识符,而 aeriesid 是学生的唯一标识符,所以我知道这两个都将只检索一条记录。

我缺少的部分是,虽然 editAdult 对象包含我想要的值,但它不是 EmbeddedDocumentListObject,因此它不包含方法。因此,上面的 get() 命令是基本的 MongoEngine get(),而不是 EmbeddedDocumentFieldList 中的 get() 方法。(我在下面显示 EmbeddedDocumentListField get())

这就是我所缺少的。这就是您在 EmbeddedDocumentListField 中使用 update() 方法的方式。

    editUser.adults.filter(oid=adultoid).update(
        relation = form.relation.data,
        fname = form.fname.data,
        lname = form.lname.data,
        ...
        notes = form.notes.data
    )

我不确定这个更新命令是否会更新所有过滤的记录。在我的情况下,只有一条记录可能被返回,因为我正在过滤一个 uniqueid。接下来,事实证明 EmbeddedDocumentListField() update() 不会像在基本 update() 方法中那样保存,因此您必须这样做。这个事实实际上在 MongoEngine 文档中有很好的记录。 http://docs.mongoengine.org/apireference.html?highlight=embedded%20documents#embedded-document-querying

editUser.adults.filter(oid=adultoid).save()

最后,还有另一种方法来执行原始的 get() 命令:

editAdult2 = editUser.adults.filter(oid=adultoid).get()

为了完整起见,这里是删除 EmbeddedDocument 记录的 Flask 路线

@app.route('/deleteadult/<aeriesid>/<adultoid>')
def deleteadult(aeriesid,adultoid):
    editUser = User.objects.get(aeriesid=aeriesid)
    editAdult = editUser.adults.get(oid=adultoid)
    editUser.adults.filter(oid=adultoid).delete()
    editUser.adults.filter(oid=adultoid).save()

我希望这对其他人有帮助。学习这一点的过程非常艰难,而且大多只是反复试验。我正在考虑回到 SQLAlchemy。:(


推荐阅读