Handling forms in Flask with Flask-WTForms

Gaurav Sharma 01 Mar, 2022 • 5 min read

This article was published as a part of the Data Science Blogathon.


We all know flask is a very rich Python framework, easy to use, simple, and hassle-free even for a beginner to start working on their web development project. Although it is a micro framework, still it provides all the stuff needed to develop your APIs or even for a web project. One such useful thing Flask provides is WTF to manage forms in a very interesting way.

Handling Forms in Flask with Flask-WTF

Image Source: hackersandslackers.com

WTF stands for WT Forms that help in providing an interactive user interface. Both Flask, as well as Django, rely heavily on this Python library WT forms. We will talk more about this in this article as we go ahead. We will also understand the concept with examples and codes. So, let’s get started.

Why Flask-WTF?

Web applications look interesting only when they have a nice and convenient user interface for the user. In HTML we have tag used for designing interface. It provides various kinds of inputs to accept such as text, textarea, integer, radio, select, etc. But a big problem with HTML forms is that it is difficult to render the form elements dynamically. And also there is no way provided by HTML to validate user input.

This is where WTForms come to the rescue. These are the flexible forms with validation and rendering library. With WTForms, you can define the form fields in Python script and then you can render them using an HTML template.

Apart from these cool features, WTForms provides these below-mentioned features also because of which it is very helpful to use this module.

  • Provides secure form with CSRF token.
  • Provides integration with WTForms.
  • Provides file upload that works with Flask Uploads.

Install Flask-WTF

To use the WT forms, install it using pip installer by the command below:

$ pip install flask-wtf

From this module, you import a Form class using which you can perform all form operations. Some of the standard form fields are:

TextField: Used to represent the text field HTML form element.

BooleanField: Used to represent the checkbox.

IntegerField: Represents text field to display the integer values.

TextAreaField: Represents text area form element.

PasswordField: Used to take the password as the form input from the user.

SubmitField: It represent the submit button of HTML. It basically replaces this piece of code of HTML:


How to use WTForms?

Now, you have installed the flask-wtf module and also got an understanding of it. So, if you want to generate a form using wtforms, you just need to follow these simple steps:

-Import the required form module and form fields like TextAreaField, IntegerField, etc.

-Next step is to create a form model.

-Display the HTML form and validate data submitted through the form, if required.

Example  of WTForms

Now, let’s not talk much and start digging more through an example. We will make a simple sign-up form. It will contain some bootstrap also to make it prettier. This whole project will be involving 4 files.

forms.py: Import the required modules and create a form model

This file will contain code to make our form using the flask-wtf module. We will then be using this file’s Form class in our HTML code.


from flask_wtf import Form  
from wtforms import validators, ValidationError  
from wtforms import TextField, IntegerField, TextAreaField, SubmitField, RadioField, SelectField  
class SignUpForm(Form):  
   name = TextField("Candidate Name ",[validators.Required("Please enter your name.")])  
   Address = TextAreaField("Address")  
   email = TextField("Email")    
   skill = SelectField('Your Skill', choices = [('excel', 'Excel'),('py', 'Python'),('draw','Draw')])  
   submit = SubmitField("Submit")

Save this code as forms.py. In this code, the first three lines are importing the modules we need. Our form will need text fields, input fields, etc. We can directly import these fields from ‘wtforms’. Next, we make a class “SignUpForm” for defining various form fields. ‘name’ variable points to the ‘Candidate Name’ text field. ‘Address’ variable points to TextField ‘Email’. ‘skill’ variable holds a dropdown having SelectField for various skills and submit variable is for ‘Submit’ button using SubmitField. We will create a single Python class per form to keep it simple for you.

app.py: Routes / Endpoints

This is the flask app we will create to render HTML pages and create simple API endpoints. In the below code, we have three routes one for the homepage: ‘/’, for the signup form we created: ‘/signup’, next is the success page as an action route for our form: ‘/success’.

from flask import Flask, render_template, request, flash
from forms import SignUpForm
app = Flask(__name__)
app.secret_key = 'development key'
def home():
    return "Home page"
@app.route('/signup', methods=['GET', 'POST'])
def signup():
    form = SignUpForm()
    return render_template('contact.html', form=form)
@app.route('/success', methods=['GET', 'POST'])
def success():
    form = SignUpForm()
    if request.method=="POST":
        print("Candidate Name:",form.name.data)
        return render_template("success.html")
if __name__ == '__main__':

Save this code as app.py. In the function signup, we imported SignUpForm class from forms.py. We pass this form as a parameter to the render_template function while rendering the contact.html page.

Setting up the secret key:

Flask-WTF by default prevents all forms from CSRF attacks. It happens by embedding a token in a hidden element () inside the form. This token is used to check the authenticity of the request. So, before flask-wtf can generate a CSRF token, a secret key is added. It is done like this in the code above:

app.secret_key = ‘development key’

This string in quotes can be anything. You can write any random characters but that should not be guessable.


In this HTML file, we will make a signup form HTML page using the form class of wtf_form. The form tag of HTML needs two things, one is action and the other is a method. Here, action is “http://localhost:5000/success” and method = “POST”.



Sign Up Form


{{ form.name.label }}

{{ form.name(class="form-control")}} 

{{ form.Address.label }}

{{ form.Address(class="form-control") }} 

{{ form.email.label }}

{{ form.email(class="form-control") }} 

{{ form.skill.label}}

{{ form.skill(class="form-control") }} 

{{ form.submit(class="btn btn-primary") }}

Inside the div class container, we use the jinja template to place value from the form.

To get label for a field from the class form use: {{ form.name.label }}

To get value for a field defined in class SignUpForm: {{ form.Address }}

If you want to apply bootstrap styling to it, you can do this way: {{ form.Address(class=”form-control”)}}.

Similarly, do for email field, skill field, and submit button also.


Data submitted successfully!

This is the HTML file to route the form after submitting the form to display data successfully submitted message.

Now, let’s have a look at the output:


Run your code: python app.py

First visit the URL: http://localhost:5000/signup

                                                          Image Source: Author

After filling in data and clicking submit you get this page:

                                                           Image Source: Author

and on the terminal, you get the submitted form data.

                                                             Image Source: Author


In this article, we saw how forms are handled in the flask using a module of python called Flask-WTF. We discussed various form fields in wtf-forms and how to use them in our HTML pages. In this article, it is explained with one example also. So, you can try that example, play around with the code and try some more examples too for better understanding.

hope you find this article helpful. Let’s connect on Linkedin.

Happy Coding! 🙂

The media shown in this article is not owned by Analytics Vidhya and are used at the Author’s discretion.

Gaurav Sharma 01 Mar 2022

Love Programming, Blog writing and Poetry

Frequently Asked Questions

Lorem ipsum dolor sit amet, consectetur adipiscing elit,

Responses From Readers


  • [tta_listen_btn class="listen"]