Flask by Example: WTForms Validation Rules
Validation ensures that the data submitted by users meets your requirements before you process it. WTForms handles this elegantly with the `validate_on_submit()` method.
Code
from flask import render_template, redirect, url_for
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
# validate_on_submit() checks if:
# 1. The request is a POST request
# 2. The CSRF token is valid
# 3. All field validators (DataRequired, Length, etc.) pass
if form.validate_on_submit():
# If we get here, data is safe and valid
print(f"Login requested for user {form.username.data}")
return redirect(url_for('index'))
# If GET request OR validation failed, render the form
# Errors are automatically attached to form fields
return render_template('login.html', form=form)
# In login.html template:
# {% for error in form.username.errors %}
# <span style="color: red;">[{{ error }}]</span>
# {% endfor %}Explanation
The validate_on_submit() method is a convenience method that checks if the request is a POST request and runs all validation rules. If validation fails, it returns False, and you can simply re-render the template.
When you re-render the template, WTForms automatically attaches error messages to the form object. This allows you to display feedback to the user next to the relevant fields without writing complex error handling logic.
This workflow follows the Post/Redirect/Get (PRG) pattern. If the form is valid, you perform the action and redirect the user; if it is invalid, you re-render the form with errors, preventing duplicate submissions on refresh.
Code Breakdown
form.validate_on_submit() encapsulates the entire validation logic. You rarely need to check request.method manually when using this.form.username.data contains the sanitized, python-native data (e.g., strings, integers, booleans) extracted from the form input.login.html, the form object retains the data the user entered, so they don't have to re-type everything. This is handled automatically by WTForms.
