简体   繁体   中英

Flask - How do I use the value of an HTML button in a Python function?

I am new to programming and have only used a little bit of Python in the past. I am using Flask to build a website to host a scientific experiment. I am doing this on pythonanywhere.com. For the last part of the experiment, participants are shown 30 individual images and they have to say if they remember seeing the image in an earlier part of the experiment.

To do this I have created a javascript function that randomly shows one of 30 images every time changeImage() is run. Below it are two buttons saying "yes" and "no". Pressing the button should change the shown image and send "yes" or "no" to the flask_app.py, along with the variable "x" from javascript. This is so the Python function can save the number of the image and what answer the participant gives.

Javascript

var array2 = new Array();
var index = 0
var x = 0
for (var i = 1; i < 31; i++) {
    array2.push(i);
}

function changeImage() {
    if (array2.length) {
        var index = Math.floor(Math.random() * array2.length);
          x = array2[index];
        var image = "/static/images/image" + x + ".jpg"
        document.getElementById('ad').src = image;
        array2.splice(index, 1);
    }
}

HTML

<body onload="changeImage()">
   <div class="w3-row-padding w3-padding-16 w3-center">
      <img id="ad" class="img-fluid" src="/static/images/image99.jpg" />

      <form action="{{ url_for('recog1') }}" id="answer" method="POST">
          <div class="w3-center">
             <input type="submit" id="answerY" value="Yes" name="Yes"
             style="width:47%;" class="w3-bar-item w3-button w3-padding-medium w3-blue"
             onclick= "changeImage();">

             <input type="submit" id="answerN" value="No" name="No"
             style="width:47%;" class="w3-bar-item w3-button w3-padding-medium w3-blue"
             onclick= "changeImage();">
          </div>
      </form>
   </body>

The problem is that I can't get my Python function to take the value of the buttons themselves. I do succesfully save data in an earlier part of the site where users have to enter their age and gender in a form, but I just can't get it to work when there are no fields to enter the data. The value from the button itself should be saved.

Python function

@app.route("/recog1", methods=["POST", "GET"])
def recog1():
    if request.method == "GET":
         return render_template("recog1.html")

    Yes = request.form['Yes']
    No = request.form['No']

    entry_time = datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')

    #save to file
    with open(BASE_DIR + '/userinfo/userinfo.csv', 'a+') as myfile:
        myfile.write(
            str(entry_time) + ', ' +
            str(Yes) + ', ' +
            str(No) + ', '
            + '\n')
        myfile.close()

    return redirect(url_for("thankyou"))

Now, there is a lot wrong with what is done with the data here and it would immediately go to the thankyou page, instead of waiting for thirty button clicks. I'll change those things later but first the problem is that I can't even get the button values to my python here. I always get "Bad Request: The browser (or proxy) sent a request that this server could not understand". I have looked at stackoverflow questions similar to this but they have never been useful to me or more likely, I didn't know how exactly to apply them to my case. Any amount of help would be greatly appreciated and thank you for taking the time to read!

EDIT: To solve the issue, the Yes = request.form['Yes'] and No = request.form['No'] in my python function needed to be replaced with x = request.form['Answer'] , where I set "Answer" as the name for both the buttons in HTML.

Try this in your python route

if request.method == 'POST':
    if "answerY" in request.form:
        print('yes button pressed')
    elif "answerN" in request.form:
        print('no button pressed')

edit1:

Try making a route like this, and then in your javascript function you could reroute to this route or handle it in your form action.

@app.route('/buttonresult/<button_id>', methods=['GET','POST'])
def buttonresult(button_id):
    yes_string = ''
    no_string = ''

    if button_id == 'answerY':
        # do something
        yes_string = 'Yes'
    elif button_id == 'answerN':
        # do something
        no_string = 'No'
    
    entry_time = datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')

    #save to file
    with open(BASE_DIR + '/userinfo/userinfo.csv', 'a+') as myfile:
        myfile.write(
            str(entry_time) + ', ' +
            str(Yes) + ', ' +
            str(No) + ', '
            + '\n')
        myfile.close()

    return redirect(url_for("thankyou"))

In order to redirect page from javascript function you can do this

# get button_id value somehow
windows.location.href = '/buttonresult/" + button_id

I think maybe I wasn't being very clear in my comment, so I'm posting this answer.

Try changing your recog1 function to the following:

@app.route("/recog1", methods=["POST"])
def recog1():
    print(request.form)
    return str(request.form)

When you press either the Yes or No button, what gets printed in your terminal/what do you see in the browser? Do you still receive the same error?


EDIT - When you press one of the two buttons, only one of the values will show up in request.form . This makes sense if you think about it - you can only ever press one of the two buttons, but not both. If you press the "Yes" button, request.form will have a key-value pair for Yes , but not for No . If you press the "No" button, request.form will have a key-value pair for No , but not for Yes . The way your code is written right now, it assumes request.form will always have both key-value pairs. This, of course, can never be true, and so regardless of what button you press, the missing key for the other one results in the error you're seeing.

You need to check for the presence of the Yes and No keys seperately, and then perform an action based on that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM