How To Use Flask-WTForms

How To Use Flask-WTForms

Make form validation a breeze

Image for postPhoto by Alejandro Escamilla on Unsplash

Meta Information


  • Introduction on how to use Flask-WTForms to simplify form generation and validation
  • Use Flask-WTForms to build a functioning Flask application with only one registration page. The end product looks like:

Image for postA registration form with a customized style

Assumption of readers

  • Know Python.
  • Know the basics of Flask.


  • The code for this article can be accessed on GitHub.

What Is Flask-WTForms

When you are building an interactive application using Flask, you can?t avoid forms. Code for creating forms and processing form data, especially form validation, can quickly grow to something that is difficult to read as well as tedious to write.

Flask-WTForms is a great tool to help with form validation (e.g., avoidance of Cross-Site Request Forgery (CSRF)). Flask-WTForms can help create and use web forms with simple Python models, turning tedious and boring form validation into a breeze.

Use Flask-WTForms

The codebase of a simple Flask application

To demonstrate the power of Flask-WTForms, we will keep our codebase to a minimum. As a result, we will stick to a single Python file and an HTML template.

To start from scratch, we create a folder named wtf-registration-form, navigate inside the folder, create and activate the virtual environment, and then install Flask:

$ python3.7 -m venv env$ source env/bin/activate(env)$ pip install flask

Our codebase has only about 10 lines:

The corresponding HTML file registration.html is purely static up to this point:

Quick form generation and validation

quick_form is a method that outputs Bootstrap-markup for a complete Flask-WTF form.

As you may guess, it relies on both Flask-Bootstrap and Flask-WTF. quick_form is one of the best demonstrations of how Flask-WTForms makes form generation and validation easy.

To use quick_form, we will need to install both Flask-Bootstrap and Flask-WTF:

(env)$ pip install flask_bootstrap(env)$ pip install Flask-WTF

Now we can move to update

There are three things that need explanation.

  1. First, we use Bootstrap and rely on it to style our form. To load the newly installed Bootstrap, you just need to say Bootstrap(app) when app (a Flask object) is initialized.

When Bootstrap is loaded, your HTML template files will have access to a set of Bootstrap template files (including HTML, CSS, and JS files) ready underneath a folder named Bootstrap in your templates folder.

You won?t be able to actually see this Bootstrap folder, and you had better refer to its manual on how to use it.

2. Second, we make an object that represents the form, and pass it to the template file named registration.html through the render_template method. As a result, we can use this form object to render the form in our HTML template file:

wtf.quick_form will generate a form that includes all sorts of stuff, such as CSFR avoidance, form validation, and default Bootstrap styles. In the above template code, it takes the form object passed through the render_template method in as the only variable.

3. Third, the form object passed through the render_template method from to registration.html is cast from a class named RegForm, and this is our own doing.

This class, with only about 15 lines, will generate a registration form that automatically validates each field when necessary:

flask_wtf is responsible for tying wtfform to the Flask framework. Our RegForm inherits the Form class from flask_wtf. For more information about the Form class under flask_wtf, check out this article.

wtfform is a class that is different from flask_wtf. When you think of handling form generation and validation, those are the jobs of wtfform. wtfform defines a set of fields that correspond to various <input> elements.

For instance, StringField corresponds to the <input> element with a type=”text”. The first parameter of StringField is the label, which represents the text label for the <input> element. The second parameter of StringField is a list of validators.

To be more specific, let?s look at this line of code in

name_first = StringField(‘First Name’, [validators.DataRequired()])

When you start your application, this line will generate the following HTML code:

<div class=”form-group required”><label class=”control-label” for=”name_first”>First Name</label><input class=”form-control” id=”name_first” name=”name_first” required=”” type=”text” value=”” autocomplete=”off”></div>

With the three files ready, you can move on and see the actual effect of quick_form by starting your Flask application:

(env)$ python3

You will see this:

Image for postA registration form with the default Bootstrap style

Note that the above style is just the default Bootstrap style. When you use quick_form, that is the best it can do.

Customized form generation and validation

When you need to customize the style of your registration form (e.g., list the inputs of first and last names in the same row, you have to give up using quick_form and manually write the style of your HTML template.

Flask-Bootstrap and Flask-WTF support another method named from_field that can listen to and parse the form object sent from to the HTML template.

For instance, the following lines put the input fields of the first and last names in the same row:

Please note that the first parameter of the from_field method is the instance that corresponds to an input field. The remaining parameters specify other attributes, such as class, placeholder, etc.

Additionally, it is worth noting that we need to include the following line in the form to avoid CSRF.

{{ form.csrf_token() }}

When we use quick_form, this part is taken care of automatically. When we make a customized form template, we have to do this manually. Overall, the customized template looks like this:

The customized template renders the following effect:

Image for postA registration form with a customized style (two fields on the same row and a blue button)

Related Stories

What I Learned from Developing a Google Docs Add-on in Two Weeks


No Responses

Write a response