In real life, we use forms to provide a service to users, for example, forms in school that ask you about the meal quality. Digital forms are used for the same purpose — to obtain a user opinion (online surveys) or to provide users access to a service. Forms in digital world are implemented with HTML.
WTForms is the library to create and work with HTML forms. It supports common functionalities like input validation, security, internationalization — the library does the heavy lifting of providing these features, and a developer can configure the library to their specifications.
Flask-WTForm is a library that provides WTForm form validation and rendering solutions in Flask.
Full stack example using WTForms
WTForms are based on HTML forms. In simplest terms, an HTML forms consists of the HTML label elements, the HTML input elements, and a submit button. Conceptually, a form can be thought of as a collection of label and input elements.
A full stack web app is a combination of frontend and backend. In flask, the frontend is typically a Jinja template, and the backend is a server that hosts a bunch of flask request handlers, which are invoked per URL matching with the configured app. With this quick refresher, let us embark on the journey to WTForms.
WTForm class
Start by installing the Flask-WTF package.
pip install -U Flask-WTF
Let's see a WTForm code example, and the corresponding UI example one by one:
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField
class BasicLoginForm(FlaskForm):
name = StringField('NAME')
# variable name represents the name input in actual HTML form
# StringField specifies type of input that is expected to be available in form for name field
# 'NAME' denotes the label, each form input has a label and that value is 'NAME' in this case
password = PasswordField('PASSWORD')
This WTForm can be used to model an HTML form which looks like
WTForms in frontend
A WTForm has fields and labels defined for the HTML form.
name = StringField('NAME')
Without a WTForm, HTML code would look as follows:
<form>
<div class="form-group">
<label for="fname">Name</label><br>
<input type="text" id="fname" name="fname"><br>
</div>
<div class="form-group">
<label for="fpass">Password</label><br>
<input type="text" id="fpass" name="fpass"><br>
</div>
</form>
With a WTForm, the field can be referenced in the HTML Jinja template using the Python form object.
<form>
<div class="form-group">
{{ form.name.label }}
{{ form.name() }}
</div>
<div class="form-group">
{{ form.password.label }}
{{ form.password() }}
</div>
</form>
The form is the instance of the WTForm object, and its label is the first parameter in the field constructor, StringField, for example. To render each field, one should simply call it inside the template. This method also allows configuring the field, refer to the documentation for details.
WTForm in backend
In backend, we deal with primarily two type of requests: GET and POST.
For GET requests, we will return the HTML template with an instance of form object, so the user can input data in the form.
For POST requests, we can read the instance of form object and fetch relevant field values like name and password for further processing.
Let us look at the GET and POST flow; note, we use the Flask request object to check the method type.
from flask import Flask, render_template, request
@app.route('/', methods=['GET', 'POST'])
def handle_form():
form = BasicLoginForm()
if request.method == 'GET':
#return the jinja template with form object as input in case of GET method
return render_template('signup_in_form.html', form=form)
if request.method == 'POST':
if form.validate_on_submit():
# read form fields easily from the WTForm object
username = form.data["name"]
password = form.data["password"]
print(username, password)
# return template in case of POST method
return render_template('signup_in_form.html', form=form)
As simple as that.
Even in this simple WTForm, we can see that we might need validation on the password field. As the form size grows and multiple fields are added, it is good practice to use WTForm in-built validation mechanism to accept or reject a form on data submission. Other form functionalities like file upload or CSRF can also be managed with WTForms. These features are going to be explained in the next topic.
Conclusion
WTForm is a tool to simplify form-based web development simple. Used with the right design, they provide a wide range of functionality, help check the form data, manage CSRF, and make it easier in the backend to focus on the business logic. WTForms can result in very advanced flows in minimal time.