Allowing a user to submit data to your web application is a universal need. No matter what web framework or solution you are using, HTML Forms are the method typically used to gather and submit data from an end-user to a web application. In this tutorial, we’ll take a look at how to get forms to work in Flask, how to get form data in Flask, and how to access various form fields when using Flask.
Add A Form To Template
In the page template, let’s add some basic markup that outlines a form. The form has an input field for a URL, an input field for a short code, two labels to describe those inputs, and a Submit input.
flask-tutorial\templates\home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Make A Short URL</title>
</head>
<body>
<h1>Make A Short URL</h1>
<form action="shortenurl">
<label for="url">Enter URL</label>
<input type="url" name="url" value="" required>
<label for="shortcode">Enter Name</label>
<input type="text" name="shortcode" value="" required>
<input type="submit" value="Submit">
</form>
</body>
</html>
Submitting Form Data
Each form has an action attribute the specifies what URL the form submits to. In order to handle that, we need the correct routes set up in app.py. Let’s modify the app.py file to reflect this. At the same time, we can add a new file to the project named shortenurl.html because that is the template that will be rendered.
flask-tutorial\app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def home():
return render_template('home.html')
@app.route('/shortenurl')
def shortenurl():
return render_template('shortenurl.html')
Inside of the shortenurl.html file, we can just add some basic markup to let the user know what page they are currently on.
flask-tutorial\templates\shortenurl.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Here Is Your URL!</title>
</head>
<body>
<h1>Here Is Your URL!</h1>
</body>
</html>
How To Access Request Data
Data associated with an HTML form is carried in the HTTP request. In order to access form request data in Flask, we can import request and use request.args.
flask-tutorial\app.py
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
def home():
return render_template('home.html')
@app.route('/shortenurl')
def shortenurl():
return render_template('shortenurl.html', shortcode=request.args['shortcode'])
The code just above uses request to fetch the data contained in <input type=”text” name=”shortcode” value=”” required>, which exists in home.html. Now, to display that data on the other page after the form has been submitted, we simply add the interpolation in the Jinja template that we explored in the flask page templates tutorial.
flask-tutorial\templates\shortenurl.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Here Is Your URL!</title>
</head>
<body>
<h1>Here Is Your URL!</h1>
<h2>{{ shortcode }}</h2>
</body>
</html>
Now we can add some data to the form, and then click submit.
Once clicked, the destination page template shows the value that was typed into the shortcode input field.
How To Make A POST Request
The code so far has the plumbing in place to get a basic form submission working in Flask. It is using a GET request, which is not that great for web forms. Instead, we should make the form use a POST request. To do this, we can make a few tweaks to the form and route.
Specify Form Action
To indicate that the form should use a POST request, we can add method=post to the opening form tag.
flask-tutorial\templates\home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Make A Short URL</title>
</head>
<body>
<h1>Make A Short URL</h1>
<form action="shortenurl" method="post">
<label for="url">Enter URL</label>
<input type="url" name="url" value="" required>
<label for="shortcode">Enter Name</label>
<input type="text" name="shortcode" value="" required>
<input type="submit" value="Submit">
</form>
</body>
</html>
Next up, we need to fix the request type in the routes of app.py. If you try to submit a form in Flask which specifies a POST request and the app.py can’t support that, you’ll get an error like: “Method Not Allowed The method is not allowed for the requested URL.” To make a route support a POST request, the highlighted code below is used.
flask-tutorial\app.py
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
def home():
return render_template('home.html')
@app.route('/shortenurl', methods=['GET', 'POST'])
def shortenurl():
return render_template('shortenurl.html', shortcode=request.args['shortcode'])
request.args vs request.form
Submitting the form now creates an error, which is not ideal.
werkzeug.exceptions.BadRequestKeyError werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand. KeyError: 'shortcode'
To fix this, we can use request.form rather than request.args in app.py.
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
def home():
return render_template('home.html')
@app.route('/shortenurl', methods=['GET', 'POST'])
def shortenurl():
return render_template('shortenurl.html', shortcode=request.form['shortcode'])
At this point, the POST request is successful, the data is displayed on the screen and there are no unsightly variables contained in the URL of the web browser.
Detecting Request Methods
A single route may support more than one request type. In fact, our code above lets the /shortenurl route support both GET and POST requests. A common pattern in cases like this is to use a Python if statement to decide how to process the request. The following update to the code checks to see if the request method is of type POST. If it is, then the shortenurl.html page template is rendered while passing one of the input fields data to the template. If a GET request is made, a simple string is returned that let’s the user know a GET request was made. If any other request was made such as PUT, PATCH, or DELETE, then we let the user know that those request methods are not supported for this specific route.
flask-tutorial\app.py
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
def home():
return render_template('home.html')
@app.route('/shortenurl', methods=['GET', 'POST'])
def shortenurl():
if request.method == 'POST':
return render_template('shortenurl.html', shortcode=request.form['shortcode'])
elif request.method == 'GET':
return 'A GET request was made'
else:
return 'Not a valid request method for this route'
Learn More About How To Use Forms In Python Flask
- Flask Mega Tutorial Web Forms (blog.miguelgrinberg.com)
- Python Advanced Web Apps Flask Forms.html (python-adv-web-apps.readthedocs.io)
- Flask Web Forms (pythonspot.com)
- Flask Wtforms Forms (hackersandslackers.com)
- Python Modules Flask Flask Forms (askpython.com)
- Flask Working With Forms (pythonise.com)
- Form Handling In Flask (overiq.com)
- Palletsprojects Patterns Wtforms (flask.palletsprojects.com)
- Python Flask Core Form Submission (opentechschool.github.io)
- How To Use Flask Wtforms (betterprogramming.pub)
- Form Validation For Your Flask App (improveandrepeat.com)
- Python Flask.request.form (programcreek.com)