How to Use Flask-WTF for Form Handling in Flask
To use
flask-wtf, install it and create form classes by inheriting from FlaskForm. Define fields and validators, then render and validate forms in your Flask routes using form.validate_on_submit().Syntax
Flask-WTF uses form classes that inherit from FlaskForm. You define form fields like StringField and add validators such as DataRequired. In your Flask route, you create a form instance, check if the form is submitted and valid with validate_on_submit(), and then process the data.
python
from flask_wtf import FlaskForm from wtforms import StringField, SubmitField from wtforms.validators import DataRequired class MyForm(FlaskForm): name = StringField('Name', validators=[DataRequired()]) submit = SubmitField('Submit') # In Flask route: # form = MyForm() # if form.validate_on_submit(): # # process form.name.data # else: # # render form
Example
This example shows a simple Flask app using Flask-WTF to create a form with a name field. It validates input and displays a greeting after submission.
python
from flask import Flask, render_template_string, 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'] = 'secret-key' class NameForm(FlaskForm): name = StringField('Enter your name', validators=[DataRequired()]) submit = SubmitField('Greet') @app.route('/', methods=['GET', 'POST']) def index(): form = NameForm() if form.validate_on_submit(): name = form.name.data return redirect(url_for('greet', username=name)) return render_template_string(''' <form method="POST"> {{ form.hidden_tag() }} {{ form.name.label }} {{ form.name(size=20) }}<br> {{ form.submit() }} </form> ''', form=form) @app.route('/greet/<username>') def greet(username): return f'Hello, {username}!' if __name__ == '__main__': app.run(debug=True)
Output
A web page with a form asking for your name. After submitting a non-empty name, it redirects to a page showing "Hello, [name]!"
Common Pitfalls
- Not setting
SECRET_KEYin Flask app config causes CSRF errors. - Forgetting to include
{{ form.hidden_tag() }}in templates breaks CSRF protection. - Using
request.formdirectly instead ofform.validate_on_submit()misses validation. - Not adding validators leads to accepting empty or invalid input.
python
from flask import Flask, render_template_string from flask_wtf import FlaskForm from wtforms import StringField, SubmitField from wtforms.validators import DataRequired app = Flask(__name__) # Missing SECRET_KEY causes CSRF errors # app.config['SECRET_KEY'] = 'secret' class BadForm(FlaskForm): name = StringField('Name') # No validators submit = SubmitField('Submit') @app.route('/', methods=['GET', 'POST']) def bad_route(): form = BadForm() if form.validate_on_submit(): return f'Hello, {form.name.data}!' return render_template_string(''' <form method="POST"> <!-- Missing hidden_tag() causes CSRF error --> {{ form.name.label }} {{ form.name(size=20) }}<br> {{ form.submit() }} </form> ''', form=form) if __name__ == '__main__': app.run(debug=True)
Quick Reference
- Install:
pip install flask-wtf - Define form: Inherit from
FlaskForm, add fields and validators. - Use in route: Create form instance, call
validate_on_submit(). - Template: Render fields and include
{{ form.hidden_tag() }}for CSRF. - Config: Set
app.config['SECRET_KEY']for security.
Key Takeaways
Always set a SECRET_KEY in your Flask app to enable CSRF protection.
Create form classes by inheriting from FlaskForm and add fields with validators.
Use form.validate_on_submit() in routes to handle form submission and validation.
Include {{ form.hidden_tag() }} in your templates to render CSRF tokens.
Validators like DataRequired ensure users enter valid data before processing.