'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

Viewed 802

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.

1 Answers

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
Related