0
0
FlaskHow-ToBeginner · 4 min read

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_KEY in Flask app config causes CSRF errors.
  • Forgetting to include {{ form.hidden_tag() }} in templates breaks CSRF protection.
  • Using request.form directly instead of form.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.