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:
Form details
Details of the submitted formExample 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
Details of the Signup form
Form submitted
Explore
Python Fundamentals
Python Data Structures
Advanced Python
Data Science with Python
Web Development with Python
Python Practice
My Profile