Reputation: 81
I am creating a database for my school. There is a Student Document that has an EmbeddedDocumentListField of Adults. I am trying to update existing EmbeddedDocuments using the EmbeddedDocumentListField methods but both save() and update() give me errors. get() seems to work though.
class Adult(EmbeddedDocument):
relation = StringField() # Adult, Mother, Father, Grandmother...
...
notes = StringField()
class Student(Document):
afname = StringField()
alname = StringField()
...
adults = EmbeddedDocumentListField('Adult')
I am able to successfully use the get method
@app.route('/editadult/<aeriesid>/<adultoid>')
def editadult(aeriesid,adultoid):
editUser = User.objects.get(aeriesid=aeriesid)
editAdult = editUser.adults.get(oid=adultoid)
This returns the object named editAdult with the attributes as expected but not the methods. I now want to update the values in that Object. I am able to see the methods I want to call by doing.
dir(editUser.adults)
But can't see the methods with
dir(editAdult)
From my reading of the docs I should be able to do this.
editAdult.update(fname="Juanita", lname="Sanchez")
This gives the error: AttributeError: 'Adult' object has no attribute 'update'. But can't figure out how to use the methods on that context. I tried
editAdult.fname = "Juanita"
editAdult.lname = "Sanchez"
editAdult.save()
But that gives the error: AttributeError: 'Adult' object has no attribute 'save'
The documentation is sparse. Mongoengine tells me what the methods are but no examples. http://docs.mongoengine.org/apireference.html#embedded-document-querying And GitHub gives good examples but I couldn't get them to work. https://github.com/MongoEngine/mongoengine/pull/826
I am using Mongoengine 0.20.0
Upvotes: 1
Views: 369
Reputation: 81
After a lot of trial and error I figured this out. With this data structure:
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')
I then created this Flask Route
@app.route('/editadult/<aeriesid>/<adultoid>')
def editadult(aeriesid,adultoid):
editUser = User.objects.get(aeriesid=aeriesid)
editAdult = editUser.adults.get(oid=adultoid)
adultoid is the unique identifier for the adult and aeriesid is the unique identifier for the student so I know that both of these will retrieve exactly one record.
The part that I was missing is that while the editAdult Object contains exactly the values that I want, it is NOT an EmbeddedDocumentListObject so it does not contain the methods. So, that get() command above is the basic MongoEngine get() and NOT the get() method from the EmbeddedDocumentFieldList. (I show the EmbeddedDocumentListField get() below)
Here is what I was missing. This is how you use the update() method in the EmbeddedDocumentListField.
editUser.adults.filter(oid=adultoid).update(
relation = form.relation.data,
fname = form.fname.data,
lname = form.lname.data,
...
notes = form.notes.data
)
I am not sure if this update command would update all of the filtered records. In my case, it is only possible that one record is returned because I am filtering on a uniqueid. Next, it turns out the EmbeddedDocumentListField() update() does NOT save like it does in the base update() method so you then have to do this. This fact is actually well documented in the MongoEngine docs. http://docs.mongoengine.org/apireference.html?highlight=embedded%20documents#embedded-document-querying
editUser.adults.filter(oid=adultoid).save()
Finally, there is another way to do the original get() command:
editAdult2 = editUser.adults.filter(oid=adultoid).get()
For the sake of completeness, here is the Flask route to delete an EmbeddedDocument record
@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()
I hope this is helpful to others. The process to learn this was crazy hard and mostly just trial and error. I considering going back to SQLAlchemy. :(
Upvotes: 1