Registry / web-framework / flask-wtf

flask-wtf

JSON →
library1.3.0pypypi✓ verified 26d ago

Flask-WTF is a Flask extension (current version 1.2.2) that simplifies form handling by integrating the WTForms library. It provides robust features such as CSRF protection, form validation, file upload support, and reCAPTCHA integration. Maintained by the Pallets organization, it generally sees regular updates, though specific release cadences can vary.

pip install Flask-WTF
INSTALL
IMPORT
SIG · FLASK-WTF
F
flask-wtf
web-frameworkpythonv1.3.0
Install
2.4s avg
Import
524ms
Disk
22MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v1.3.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.95 runs
installs and imports cleanly · install 0.0s · import 0.544s · 23.7MB
glibc
py 3.103.95 runs
installs and imports cleanly · install 2.4s · import 0.504s · 24MB
22MB installed
● package 22MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

FlaskForm
from flask_wtf import FlaskForm
from flask_wtf import Form
`Form` was deprecated and removed in favor of `FlaskForm` in versions >= 1.0.0. `FlaskForm` is a Flask-specific subclass of WTForms' `Form` that includes CSRF protection.
StringField
from wtforms import StringField
from flask_wtf import StringField
Since version 0.9.0, fields (e.g., `StringField`, `PasswordField`) must be imported directly from `wtforms`, not `flask_wtf`.
DataRequired
from wtforms.validators import DataRequired
Validators are imported directly from `wtforms.validators`.

This quickstart demonstrates a basic Flask application using Flask-WTF to create, render, and validate a simple form. It includes defining a `FlaskForm` subclass, rendering it in an HTML template, and processing its submission with `validate_on_submit()`.

import os from flask import Flask, render_template, request, redirect, url_for from flask_wtf import FlaskForm from wtforms import StringField, SubmitField from wtforms.validators import DataRequired app = Flask(__name__) app.config['SECRET_KEY'] = os.environ.get('FLASK_SECRET_KEY', 'a_very_secret_key_for_dev') class MyForm(FlaskForm): name = StringField('Name', validators=[DataRequired()]) submit = SubmitField('Submit') @app.route('/', methods=['GET', 'POST']) def index(): form = MyForm() if form.validate_on_submit(): name = form.name.data print(f"Form submitted with name: {name}") # In a real app, save 'name' to a database, etc. return redirect(url_for('success', name=name)) return render_template('index.html', form=form) @app.route('/success/<name>') def success(name): return f'Hello, {name}! Your form was submitted successfully.' if __name__ == '__main__': # Example template content (save as templates/index.html) # <form method="POST" action="/"> # {{ form.hidden_tag() }} # <p> # {{ form.name.label }} # {{ form.name(size=30) }} # {% if form.name.errors %} # <ul class="errors"> # {% for error in form.name.errors %} # <li>{{ error }}</li> # {% endfor %} # </ul> # {% endif %} # </p> # <p>{{ form.submit() }}</p> # </form> app.run(debug=True)
Debug
Known issues
breakingThe base form class `flask_wtf.Form` was deprecated and removed. Applications should now import and inherit from `flask_wtf.FlaskForm`.
fix
Change `from flask_wtf import Form` to `from flask_wtf import FlaskForm`.
affects: >=1.0.0 (Introduced in 0.9.0 with `FlaskForm`, `Form` removed in 1.0.0)
breakingWTForms fields (e.g., `StringField`, `IntegerField`) are no longer imported from `flask_wtf`.
fix
Import fields directly from `wtforms` (e.g., `from wtforms import StringField`).
affects: >=0.9.0
gotchaCSRF protection requires `app.config['SECRET_KEY']` to be set to a strong, random string. Without it, Flask-WTF's CSRF features will not work, or forms will fail validation.
fix
Set a secure `SECRET_KEY` in your Flask app's configuration, ideally loaded from an environment variable: `app.config['SECRET_KEY'] = os.environ.get('FLASK_SECRET_KEY', 'fallback-secret-key')`.
affects: All versions
gotchaFor forms that include `FileField` for file uploads, the HTML form tag must include `enctype="multipart/form-data"` to ensure file data is correctly sent to the server.
fix
Add `enctype="multipart/form-data"` to your HTML `<form>` tag when handling file uploads.
affects: All versions
gotchaThe `form.validate_on_submit()` method only validates if the request method is POST, PUT, PATCH, or DELETE. It will always return `False` for GET requests, which can be a common source of confusion.
fix
Use `form.validate_on_submit()` for handling form submissions (typically POST). For displaying an initial form (GET), simply create the form instance without calling `validate_on_submit()`.
affects: All versions
breakingThe application experienced a timeout during execution. While this is a general execution issue rather than a specific API misuse, it can sometimes be triggered by complex or misconfigured form processing, custom validators, or template rendering involving Flask-WTF. Reviewing related logic for infinite loops or resource-intensive operations is crucial.
fix
Examine the application's logs for any errors or warnings that precede the timeout. Use a debugger or profiling tools to identify bottlenecks or infinite loops in form validation, processing, or rendering paths. Ensure custom validators and data handling routines are efficient and terminate correctly.
affects: All versions
Errors
Common errors & fixes
400 Bad Request: The CSRF token is missing
The Flask application's `SECRET_KEY` is not set, the CSRF token is not rendered in the HTML form, or the session holding the token is not persisting correctly.
fix
Set a strong `app.secret_key` in your Flask configuration. In your HTML form, ensure you render the CSRF token using `{{ form.csrf_token }}` or `{{ form.hidden_tag() }}` inside the `<form>` tags.
ModuleNotFoundError: No module named 'flask_wtf'
The `flask-wtf` library is either not installed in your current Python environment or the environment where it's installed is not active.
fix
Install the library using pip: `pip install flask-wtf`. If using a virtual environment, ensure it is activated before running your application.
jinja2.exceptions.UndefinedError: 'form' object has no attribute 'csrf_token'
This error typically occurs when a form object passed to a Jinja2 template is not an instance of `flask_wtf.FlaskForm`, or when CSRF protection is disabled (e.g., `WTF_CSRF_ENABLED = False`) but the template still attempts to access `form.csrf_token` without checking its existence.
fix
Ensure your form class inherits from `flask_wtf.FlaskForm`. If intentionally disabling CSRF (e.g., during testing), update your template to conditionally render the token: `{% if form.csrf_token %}{{ form.csrf_token }}{% endif %}`.
`form.validate_on_submit()` always returns False
This usually indicates that the form submission failed validation, most commonly due to a missing or invalid CSRF token, or other client-side input validation failures that are not immediately apparent.
fix
First, ensure `app.secret_key` is configured and `{{ form.csrf_token }}` or `{{ form.hidden_tag() }}` is present in your HTML form. To debug other validation issues, print `form.errors` after `form.validate_on_submit()` to see specific field validation messages.
Upgrade
Version history
1.3.0latest on PyPI · released Apr 23, 2026
Audit
Dependencies
FlaskrequiredCore web framework integration.
WTFormsrequiredUnderlying form validation and rendering library.
itsdangerousrequiredUsed for secure token signing, including CSRF tokens.
email-validatoroptionalProvides an Email validator, required for 'email' extra.
Agent activity
42 hits · last 30 days
node
36
Amazon
1
OpenAI (training)
1
Resources
flask-wtf — pip install flask-wtf · libregistry