Mongoengine EmbeddedDocumentListField // Я могу получить доступ только к методу get - PullRequest
0 голосов
/ 17 июня 2020

Я создаю базу данных для своей школы. Существует студенческий документ, в котором есть EmbeddedDocumentListField для взрослых. Я пытаюсь обновить существующие EmbeddedDocuments с помощью методов EmbeddedDocumentListField, но и 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: объект «Взрослый» не имеет атрибута «save»

Документация скудна. Mongoengine говорит мне, что это за методы, но без примеров. http://docs.mongoengine.org/apireference.html#embedded -document-querying И GitHub дает хорошие примеры, но я не мог заставить их работать. https://github.com/MongoEngine/mongoengine/pull/826

Я использую Mongoengine 0.20.0

1 Ответ

0 голосов
/ 17 июня 2020

После множества проб и ошибок я понял это. С этой структурой данных:

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 Маршрут

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

адултоид - уникальный идентификатор для взрослого, а аэриесид - уникальный идентификатор для ученика, поэтому я знайте, что оба они получат ровно одну запись.

Часть, которую мне не хватало, заключается в том, что хотя объект editAdult содержит именно те значения, которые мне нужны, он НЕ является объектом EmbeddedDocumentListObject, поэтому он не содержит методов. Итак, приведенная выше команда get () является базовым c MongoEngine get (), а НЕ методом get () из EmbeddedDocumentFieldList. (Я показываю EmbeddedDocumentListField get () ниже)

Вот то, что мне не хватало. Вот как вы используете метод update () в EmbeddedDocumentListField.

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

Я не уверен, что эта команда обновления обновит все отфильтрованные записи. В моем случае возможно, что будет возвращена только одна запись, потому что я фильтрую по уникальному идентификатору. Затем выясняется, что EmbeddedDocumentListField () update () НЕ сохраняет, как в базовом методе update (), поэтому вам нужно это сделать. Этот факт действительно хорошо задокументирован в документации MongoEngine. http://docs.mongoengine.org/apireference.html?highlight=embedded%20documents#embedded -запрос документа

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

Наконец, есть еще один способ выполнить исходную команду get ():

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

Ради полнота, вот путь Flask для удаления записи EmbeddedDocument

@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. : (

...