Search code examples
pythonhtmlflask

Having 2 forms in 1 html file raises error: 400 Bad Request (flask)


I recently started learning flask and i ran into an issue that happens when 1 html file has 2 forms that can be submitted. This issue does not happen when there is only one form.

This is my python file containing flask:

from flask import Flask, request, render_template

app = Flask(__name__)
app.secret_key = 'secretkry'

@app.route("/", methods=["GET", "POST"])
def index():
    if request.method == "POST":
        if request.form["form_button_1"]:
            return render_template('index.html', test_id="pressed form nr 1")
        if request.form["form_button_2"]:
            return render_template('index.html', test_id="pressed form nr 2")

    return render_template('index.html', test_id="hasnt yet pressed form button")

if __name__ == '__main__':
    app.run(port=44444)

And this is my index.html file

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form action="#" method="post">
    <button name="form_button_1" type="submit" value="random_value1">form button 1</button>
</form>

<br>

<form action="#" method="post">
    <button name="form_button_2" type="submit" value="random_value2">form button 2</button>
</form>

<p>{{test_id}}</p>

</body>
</html>

When I run this I get error: 400 Bad Request. This does not happen when I only have 1 form in index.html (index.html would look like this)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form action="#" method="post">
    <button name="form_button_1" type="submit" value="random_value1">form button 1</button>
</form>

<br>

<p>{{test_id}}</p>

</body>
</html>

And the python file containing flask would look like this

from flask import Flask, request, render_template

app = Flask(__name__)
app.secret_key = 'secretkry'

@app.route("/", methods=["GET", "POST"])
def index():
    if request.method == "POST":
        if request.form["form_button_1"]:
            return render_template('index.html', test_id="pressed form nr 1")

    return render_template('index.html', test_id="hasnt yet pressed form button")

if __name__ == '__main__':
    app.run(port=44444)

Again, the first example does not work, but the second one (that has only 1 form) works. I would like to know how to submit the form that was clicked on, when there are 2 forms present. I am on Kali Linux, if that makes a difference somehow. Thanks in advance


Solution

  • The request.form dictionary will only contain the button from the form that you submitted. When you try to access the other button, you'll get an error. You need to check if the name is in the dictionary, not the value of the dictionary element:

    @app.route("/", methods=["GET", "POST"])
    def index():
        if request.method == "POST":
            if "form_button_1" in request.form:
                return render_template('index.html', test_id="pressed form nr 1")
            elif "form_button_2" in request.form:
                return render_template('index.html', test_id="pressed form nr 2")
    
        return render_template('index.html', test_id="hasnt yet pressed form button")
    

    Another option would be to give the buttons the same name, and check the values:

    <form action="#" method="post">
        <button name="form_button" type="submit" value="random_value1">form button 1</button>
    </form>
    
    <br>
    
    <form action="#" method="post">
        <button name="form_button" type="submit" value="random_value2">form button 2</button>
    </form>
    

    then

    @app.route("/", methods=["GET", "POST"])
    def index():
        if request.method == "POST":
            if request.form["form_button"] == "random_value1":
                return render_template('index.html', test_id="pressed form nr 1")
            elif request.form["form_button"] == "random_value2":
                return render_template('index.html', test_id="pressed form nr 2")
    
        return render_template('index.html', test_id="hasnt yet pressed form button")