DEV Community

Cover image for Form Handling in Flask: Unleashing the Power of Flask-WTF

Posted on

Form Handling in Flask: Unleashing the Power of Flask-WTF

Handling forms is a crucial aspect of web development, and Flask, a lightweight and powerful web framework for Python, offers an excellent extension called Flask-WTF that simplifies form handling. Flask-WTF seamlessly integrates with WTForms, a flexible form handling library, providing features like form validation, CSRF protection, and form rendering. In this guide, I will walk you through the process of handling forms in Flask using Flask-WTF, empowering you to effortlessly create and process forms in your Flask applications.

What is Flask-WTF?
Flask-WTF is a built-in module of Flask that provides an alternative way of designing forms in Flask. It seamlessly integrates with WTForms, a flexible form handling library for Python.

Features of Flask-WTF:
Flask-WTF offers several features that simplify form handling in Flask, including:

Global CSRF protection: Flask-WTF provides built-in protection against cross-site request forgery (CSRF) attacks, ensuring the security of your forms.

Integration with web forms: Flask-WTF allows you to define form classes using WTForms, making it easy to create and manage form fields, validation rules, and rendering.

reCAPTCHA support: Flask-WTF supports the integration of reCAPTCHA, a popular anti-bot service, into your forms, enhancing security and preventing spam.

File upload support: Flask-WTF works seamlessly with Flask Uploads, enabling easy handling of file uploads in your forms.

Creating a Simple Contact Form using Flask-WTF
To illustrate how to use Flask-WTF, let's create a simple contact form. Here are the steps involved:

Environment set up
Install virtual environment (virtualenv)

Virtualenv is a highly useful tool that allows Python developers to create isolated environments for their projects. By isolating the environment, it ensures that the project dependencies are separate from the global Python installation, preventing conflicts between different projects.
To install Virtualenv, you can use the following command:

pip install virtualenv
Enter fullscreen mode Exit fullscreen mode

After installing Virtualenv, you can proceed to create a new virtual environment within a specific folder. For example, let's create a folder called "flaskforms" and navigate into it:

$ mkdir flaskforms
$ cd flaskforms
Enter fullscreen mode Exit fullscreen mode

Next, create the virtual environment by running the following command:

$ virtualenv venv
Enter fullscreen mode Exit fullscreen mode

Please note that the above command creates a virtual environment named "venv" in the current directory.

In case you are using Windows, you can activate the virtual environment with the following command:

$ venv\Scripts\activate
Enter fullscreen mode Exit fullscreen mode

On other operating systems like macOS or Linux, the activation command will be slightly different:

$ source venv/bin/activate
Enter fullscreen mode Exit fullscreen mode

Once the virtual environment is activated, you can proceed to install Flask, a popular web framework for Python, by using the following command:

pip install flask
Enter fullscreen mode Exit fullscreen mode

To leverage the power of WTForms, a library for form handling in Flask, you need to install the flask-wtf library. You can install it by running the following command:

pip install flask-wtf
Enter fullscreen mode Exit fullscreen mode

With these steps completed, you are now equipped with a virtual environment containing Flask and Flask-WTF installed, allowing you to handle forms seamlessly in your Flask application.

Step 1: Import necessary modules

from flask import Flask, render_template, request
from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, SubmitField
from wtforms.validators import DataRequired, Email

Enter fullscreen mode Exit fullscreen mode

Here, you import the required modules for your Flask application. The Flask module handles the web application, render_template is used to render HTML templates, and request is used to handle HTTP requests. The FlaskForm class from flask_wtf is imported to create the form, while the field types (StringField, TextAreaField, SubmitField) and validators (DataRequired, Email) from wtforms are imported to define form fields and validation rules.
Step 2: Create Flask application and set secret key

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

Enter fullscreen mode Exit fullscreen mode

You create a Flask application instance and set the secret key. The secret key is used to protect against security vulnerabilities like Cross-Site Request Forgery (CSRF).

Step 3: Define the ContactForm class

class UserContactForm(FlaskForm):
    Firstname = StringField('firstname', validators=[DataRequired()])
    Lastname = StringField('lastname', validators=[DataRequired()])
    email = StringField('Password', validators=[DataRequired(), Email()])
    text_message = TextAreaField('message', validators=[DataRequired()])
    send = SubmitField('Send')

Enter fullscreen mode Exit fullscreen mode

Here, you define the ContactFormclass that inherits from FlaskForm. Each field (Firstname, Lastname, email, text_message) is assigned a field type and associated validators. The field types (StringField, TextAreaField, SubmitField) define the input type, while validators (DataRequired, Email) specify the validation rules for each field.

Step 4: Define the contact route

@app.route('/user-contact', methods=['GET', 'POST'])
def user_contact():
    form = UserContactForm()

    if form.validate_on_submit():
        return 'Form  has been succesfully submitted'

    return render_template('user_contact.html', form=form)

Enter fullscreen mode Exit fullscreen mode

This code defines the /user-contact route for your Flask application, which can handle both GET and POST requests. Inside the user_contact function, an instance of the UserContactForm class is created. If the form is submitted and passes the validation (form.validate_on_submit()), the string 'Form submitted'is returned. Otherwise, the user_contact.html template is rendered with the form object passed to it.

Step 4: Create the HTML template
Certainly! Here's an example of how you can render the UserContactForm in an HTML template:

<!-- contact.html -->

    <title>User Contact Form</title>
    <link rel="stylesheet" href="static/css/style.css">
        body {
            background-color: #f2f2f2;
            font-family: Arial, sans-serif;

        .container {
            max-width: 400px;
            margin: 0 auto;
            padding: 20px;
            background-color: #fff;
            border-radius: 5px;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);

        .form-control {
            margin-bottom: 20px;

        .form-control label {
            font-weight: bold;
            display: block;

        .form-control input, .form-control textarea {
            width: 100%;
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 4px;

        .form-control input[type="submit"] {
            background-color: #4CAF50;
            color: #fff;
            border: none;
            cursor: pointer;

        .form-control input[type="submit"]:hover {
            background-color: #45a049;
    <div class="container">
        <h1>Contact Us</h1>
        <form method="POST" action="{{ url_for('user_contact') }}" class="form-control">

            {{ form.csrf_token }}

            <label>{{ form.Firstname.label }}</label>
            {{ form.Firstname }}
            <label>{{ form.Lastname.label }}</label>
            {{ form.Lastname }}
            <label>{{ }}</label>
            {{ }}
            <label>{{ form.text_message.label }}</label>
            {{ form.text_message }}
            {{ form.send }}


Enter fullscreen mode Exit fullscreen mode

In the above HTML template, we define a form that uses the POST method to submit the data to the /user-contact route. We include the CSRF token {{ form.csrf_token }} for security purposes.

Each field of the form is rendered using the {{ form.field_name }} syntax, where field_name corresponds to the fields defined in the UserContactForm class (Firstname, Lastname, email, text_message, send). The labels for each field are accessed using {{ form.field_name.label }}.

Top comments (0)