Open In App

Flask - WTF

Last Updated : 19 Mar, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Flask-WTF is a Flask extension that integrates the WTForms library, making form creation and validation easier in Flask applications. It provides a structured way to build forms, handle validation, and render them in HTML. In this article, we'll explore how Flask-WTF works by building a Signup form. Before diving in, let's go over its features, field types, and prerequisites.

Some of the key features of Flask-WTF include:

  • Secure Form Handling – Automatically manages CSRF protection to prevent unauthorized submissions.
  • Easy Form Rendering – Supports various field types like text fields, checkboxes, and dropdowns for smooth HTML integration.
  • Built-in Validation – Includes required fields, length constraints, pattern matching, and support for custom validation.
  • File Uploads – Allows users to upload files through forms seamlessly.

Prerequisites - Python, HTML, CSS, Javascript

Installation

To use Flask-WTF, we first need to install it using pip and import it into our application.

pip install flask-WTF

In Flask-WTF, forms are defined as classes that extend the FlaskForm class. Fields are declared as class variables, making form creation simple and structured.

Common WTForms Field Types:

  • StringField: Text input field for string data.
  • PasswordField: Input field for password values.
  • BooleanField: Checkbox for True/False selection.
  • DecimalField: Input field for decimal values.
  • RadioField: Group of radio buttons for single selection.
  • SelectField: Dropdown list for single selection.
  • TextAreaField: Multi-line text input field.
  • FileField: File upload field.

Flask - WTF Examples

Example 1

Building a sample form using the above field types

Python
# Importing Libraries..
from flask import Flask, render_template, request
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField
from wtforms import DecimalField, RadioField, SelectField, TextAreaField, FileField
from wtforms.validators import InputRequired
from werkzeug.security import generate_password_hash

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secretkey'


class MyForm(FlaskForm):
    name = StringField('Name', validators=[InputRequired()])
    password = PasswordField('Password', validators=[InputRequired()])
    remember_me = BooleanField('Remember me')
    salary = DecimalField('Salary', validators=[InputRequired()])
    gender = RadioField('Gender', choices=[
                        ('male', 'Male'), ('female', 'Female')])
    country = SelectField('Country', choices=[('IN', 'India'), ('US', 'United States'),
                                              ('UK', 'United Kingdom')])
    message = TextAreaField('Message', validators=[InputRequired()])
    photo = FileField('Photo')


@app.route('/', methods=['GET', 'POST'])
def index():
    form = MyForm()
    if form.validate_on_submit():
        name = form.name.data
        password = form.password.data
        remember_me = form.remember_me.data
        salary = form.salary.data
        gender = form.gender.data
        country = form.country.data
        message = form.message.data
        photo = form.photo.data.filename
        return f'Name: {name} <br> Password: {generate_password_hash(password)} <br> Remember me: {remember_me} <br> Salary: {salary} <br> Gender: {gender} <br> Country: {country} <br> Message: {message} <br> Photo: {photo}'
        <br > Remember me: {remember_me} < br > Salary: {salary} < br > Gender: {gender}
        <br > Country: {country} < br > Message: {message} < br > Photo: {photo}'
    return render_template('index.html', form=form)


if __name__ == '__main__':
    app.run()
HTML
<!DOCTYPE html>
<html>
<head>
    <title>My Form</title>
</head>
<body>
    <h1>My Form</h1>
    <form method="post" action="/" enctype="multipart/form-data">
        {{ form.csrf_token }}
        <p>{{ form.name.label }} {{ form.name() }}</p>
        <p>{{ form.password.label }} {{ form.password() }}</p>
        <p>{{ form.remember_me() }} {{ form.remember_me.label }}</p>
        <p>{{ form.salary.label }} {{ form.salary() }}</p>
        <p>{{ form.gender.label }} {{ form.gender() }}</p>
        <p>{{ form.country.label }} {{ form.country() }}</p>
        <p>{{ form.message.label }} {{ form.message() }}</p>
        <p>{{ form.photo.label }} {{ form.photo() }}</p>
        <p><input type="submit" value="Submit"></p>
    </form>
</body>
</html>

Explanation:

  • Created a Form Class: MyForm inherits from FlaskForm and includes various fields like StringField, PasswordField, BooleanField, etc., with appropriate validators.
  • Passed Form to Template: In the index function, an instance of MyForm is created and sent to index.html.
  • Handled Form Submission: The validate_on_submit method checks if the form is valid before processing data.
  • Retrieved and Displayed Data: If valid, form data is extracted and shown in the browser.
  • Secured Passwords: Used generate_password_hash to encrypt passwords for better security.

Output:

Flask-Forms
Form details
submitted-forms
Details of the submitted form

Example 2

Let's see another example of a simple Sign-up form using the Flask-WTF library where we use the field types mentioned above in our application.

Python
from flask import Flask, render_template
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField ,SubmitField
from wtforms.validators import InputRequired, Length

app = Flask(__name__)

app.config['SECRET_KEY'] = 'secret'

# Using StringField, PasswordField andSubmitField from Flask-WTForms library 
# for username,password fields and submit button..  
class LoginForm(FlaskForm):
    username = StringField('Username', validators=[InputRequired('Username required!'), 
               Length(min=5, max=25, message='Username must be in 5 to 25 characters')])
    password = PasswordField('Password',validators=[InputRequired('Password required')])
    submit = SubmitField('Submit')
    
@app.route('/Signup', methods=['GET', 'POST'])
def form():
    form = LoginForm()
    if form.validate_on_submit():
        return '<h1>Hi {}!!. Your form is submitted successfully!!'.format(form.username.data)
    return render_template('Signup.html', form=form)

if __name__ == '__main__':
    app.run(debug=True)

Signup.hml code

HTML
<!DOCTYPE html>
<html>
<head>
<title>Flask Form</title>
</head>
<body>
<h1>Signup </h1>
<form method="POST" action="{{ url_for('form') }}">
    {{ form.csrf_token }}
    {{ form.username.label }}
    {{ form.username }}
    <br>
    <br>
    {{ form.password.label }}
    {{ form.password }}
    <br>
    <br>
    {{ form.submit }}
</form>
</body>
</html>

Explanation:

  • {{ form.csrf_token }} adds a hidden input field to the form that contains a CSRF token. This is a security feature that helps prevent cross-site request forgery attacks.
  • {{ form.username.label }} renders an HTML label for the username field of the form.
  • {{ form.username }} renders an HTML input element for the username field of the form.
  • {{ form.password.label }} renders an HTML label for the password field of the form.
  • {{ form.password }} renders an HTML input element for the password field of the form.
  • {{ form. submit }} renders an HTML input element for the form's submit button.
     

In our Flask route, we used request.method to check if the form was submitted. The form is validated and processed only after submission. Once submitted successfully, a message is displayed along with the username. 

Output:

signup-form
Signup form 
details-of-signup-form
Details of the Signup form
submitted-form
Form submitted

Next Article
Article Tags :
Practice Tags :

Similar Reads