Form Handling in Flask: Unleashing the Power of Flask-WTF
Published: 2023-11-30 07:59:58

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
```

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
```

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

```
$ virtualenv venv
```

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
```

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

```
$ source venv/bin/activate
```

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
```

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
```

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

```
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'

```
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')

```

Here, you define the `ContactForm `class 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)

```

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 -->

<html>
<head>
    <title>User Contact Form</title>
    <link rel="stylesheet" href="static/css/style.css">
    <style>
        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;
        }
    </style>
</head>
<body>
    <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 }}
            <br>
            <label>{{ form.Lastname.label }}</label>
            {{ form.Lastname }}
            <br>
            <label>{{ form.email.label }}</label>
            {{ form.email }}
            <br>
            <label>{{ form.text_message.label }}</label>
            {{ form.text_message }}
            <br><br>
            {{ form.send }}

        </form>
    </div>
</body>
</html>

```
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 }}`.