Vasilis Skentos
Vasilis Skentos

Reputation: 566

pymongo.errors.InvalidOperation: cannot set options after executing query

I'm working on a project using flask and pymongo and I have a users collection and a movies collection where instances are like :

 user = {"Email":"[email protected]" , "Comments":[" Hobbit 2013 :good movie" , " Hobbit 2013 :bad movie" , " Spiderman 2020 :very good"]}

I also have a movies collection where a movie instance is like :

movie = {"title":"Hobbit" , "year":"2013" , "comments":["Hobbit 2013 [email protected]:good movie"] }

I am using a jinja 2 template to submit a new title to a specific movie and if any user has commented on the movie I want for every user who has commented on the specific movie to have the new movie name in his comments ex. Hobbit -> Avengers then for the above user instance

`user = {"Email":"[email protected]" , "Comments":[" Avengers  2013 :good movie" , " Avengers 2013 :bad movie" , " Spiderman 2020 :very good"]}`  
`movie = {"title":"Avengers" , "year":"2013" , "comments":["Avengers 2013 [email protected]:good movie"] }` #obviously a movie can have more comments from users not just one 

Using a flask endpoint I am succesfull in changing the movie title however I cannot change any user comment where the old movie title was as the title does not chage with my code

This is my endpoint . I get the new title from the jinja2 form and then try to replace the old title in the comments with the new . Then I get the error

pymongo.errors.InvalidOperation: cannot set options after executing query

My code :

@app.route('/executemovieupdate' , methods = ['GET', 'POST'])
def execute_movie_update():
    if 'Email' in session and 'User' in session:
        email = session['Email']
        user = session['User']
        if user == 'Admin':
            if 'Movie' in session and 'Movie_year' in session and 'Movie_plot' in session:
                movie = session['Movie']
                old_movie  = str(movie) #store old movie title 
                print("old movie is " , old_movie)
                year = session['Movie_year']
                plot = session['Movie_plot']
                tainia = movies.find_one({'title':movie , "year":year})
                if request.method == 'POST':
                    new_title = request.form.get('new-title') #get the new title from jinja2 template 

            

                    if new_title:
                       print("update the title")
                       movies.update_one({"title":movie , "year":year} , {"$set":{"title":new_title} } ) #the title is updated succesfully for the movie 
                       session['Movie'] = new_title
                       movie = session['Movie']
                       user_list = users.find({})
                       for idxu, usr in enumerate(user_list): #this is where i try to change the title in the user comments 
                            for idxc, comment in enumerate(usr['Comments']):
                                if  old_movie in comment:
                                    print("old comment here")
                                    print(comment)
                                    user_list[idxu]['Comments'][idxc] = comment.replace(old_movie ,new_title) #this is the line where the error occurs
                                    print(comment) # the new comment is printed

                    return ''' movie has been updated '''
                                                                                                      
            else:
                return render_template('movie-update.html' , movie = tainia)        
        else:
            return redirect(url_for('admin.html'))    
    else:
        return redirect(url_for('login')) 
else:
    return redirect(url_for('login'))    

I would appreciate your help with this issue . Thank you in advance.

Upvotes: 2

Views: 8942

Answers (1)

ExplodingGayFish
ExplodingGayFish

Reputation: 2897

if you print type(user_list) you will notice it's not a list of dict but a pymongo.cursor.Cursor object (which is read-only), so you can change user_list = users.find({}) to user_list = list(users.find({})) (but be cautious it will query all record from collection users) and it should work.

Another better way is to use usr['Comments'][idxc] (which is a dict) instead of user_list[idxu]['Comments'][idxc]

If you want to update that record into MongoDB then you will need to use the update_one like above

I don't have your data but something like this should do the trick:

for idxu, usr in enumerate(user_list): #this is where i try to change the title in the user comments 
    for idxc, comment in enumerate(usr['Comments']):
        if  old_movie in comment:
            print("old comment here")
            print(comment)
            usr['Comments'][idxc] = comment.replace(old_movie ,new_title) #this is the line where the error occurs
            print(comment) # the new comment is printed
    users.update_one({"_id": usr['_id']}, {"$set": {"Comments": usr['Comments']}})

Upvotes: 5

Related Questions