I am using tornado to build a simple website with mongoDB. I used python 3.7 and latest version of pymongo to control data in MongoDB but when I edit data in MongoDB with save
methods as code below, the following error occurred:
TypeError: 'Collection' object is not callable. If you meant to call the 'save' method on a 'Collection' object it is failing because no such method exists.
def post(self, isbn=None):
import time
book_fields = ['isbn', 'title', 'subtitle', 'image', 'author', 'date_released', 'description']
burtbook = self.application.db.BurtBook
book = dict()
if isbn:
book = burtbook.find_one({"isbn":isbn})
for key in book_fields:
book[key] = self.get_argument(key, None)
if isbn:
burtbook.save(book)
else:
book['add_released'] = int(time.time())
burtbook.insert_one(book)
self.redirect("/recommended/")
Please help me to fix this bug.
well, i dont know why, but i think there is a bug with save
or its deprecated
since end of 2020?
the savior method will be: update_one($old_document, $keys_to_update)
i saw on this reference that you can update in place a document
and keep the ObjectID
unmodified (you will have the original document id)
your code will become (comments will explain everything)
def post(self, isbn=None):
import time
book_fields = ['isbn', 'title', 'subtitle', 'image', 'author', 'date_released', 'description']
burtbook = self.application.db.BurtBook
book = dict()
if isbn:
book = burtbook.find_one({"isbn": isbn})
# set is a specifier to mongo to update the values;
# you just need to pass which value to modify on which key
# example
# keys_to_update = {"$set": { "bookName": "newNameSetByYou"}}
# but the bookName key name remains the same
keys_to_update = {"$set": {}}
for key in book_fields:
value = self.get_argument(key, None)
book[key] = value
if isbn:
# here if isbn we create that dictionary to tell
# mongo which value to modify on which key
keys_to_update["$set"].update({
key: value
})
# simple and old pythonic dict update
if isbn:
# here we update the document book with new values
# from the above generated dict
burtbook.update_one(book, keys_to_update)
# just like the save()
# save is deprecated boys, cant use it anymore ...
else:
book['add_released'] = int(time.time())
burtbook.insert_one(book)
self.redirect("/recommended/")
okey, on my defense, i couldnt test your code, but i've tested the same technique on my project and it know that it works for me.
just tell me if it works. pace
EDIT
another helpful reference
and also you can try this code too (here you replace the entire document with whatever you want):
todos_collection = get_collection(todos_collection_name)
requested_todo = todos_collection.find_one({
"_id": ObjectId(oid)
})
todos_collection.replace_one(requested_todo, {"something": "else"})
# this will replace the entire document `request_todo` with `{"something": "else"}`
# but it will keep the original `ObjectID`
# and thats is very useful