Flask Forms

6 Kernkonzepte
Die wichtigsten Flask-Konzepte für Formulare mit WTForms: Flask-WTF · Form Fields · Validierung · CSRF-Schutz · File Upload · Rendering Flask-WTF ist die Standard-Erweiterung für Formularverarbeitung in Flask. Sie bietet integrierte Validierung, CSRF-Schutz und einfache Integration mit WTForms.

Flask-WTF – Formulare mit WTForms

FlaskForm · StringField · SubmitField
# forms.py 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('Absenden')

Flask-WTF ist die offizielle Erweiterung für Formulare. Sie basiert auf WTForms und fügt CSRF-Schutz, Datei-Upload und Integration mit Flask hinzu.

Installation

Befehl Beschreibung
pip install flask-wtf Flask-WTF installieren (inkl. WTForms)
pip install email-validator Für EmailField-Validierung
SECRET_KEY Für CSRF-Schutz erforderlich
Beispiele
# forms.py – Formular definieren
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField, TextAreaField, IntegerField, FloatField, SelectField, RadioField
from wtforms.validators import DataRequired, Length, Email, EqualTo, NumberRange, Optional
class RegistrationForm(FlaskForm):
username = StringField('Benutzername', validators=[DataRequired(), Length(min=3, max=20)])
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Passwort', validators=[DataRequired(), Length(min=6)])
confirm = PasswordField('Passwort bestätigen', validators=[DataRequired(), EqualTo('password')])
terms = BooleanField('AGB akzeptieren', validators=[DataRequired()])
submit = SubmitField('Registrieren')
# app.py – Formular in Route verwenden
from forms import RegistrationForm
@app.route('/register', methods=['GET', 'POST'])
def register():
form = RegistrationForm()
if form.validate_on_submit():
# Formular verarbeiten
return 'Erfolg!'
return render_template('register.html', form=form)
Tipp: validate_on_submit() prüft sowohl CSRF-Token als auch alle Validatoren – das ist die einfachste und sicherste Methode zur Formularverarbeitung.

Feldtypen – Die wichtigsten WTForms-Felder

StringField · IntegerField · SelectField · DateField
name = StringField('Name', validators=[DataRequired()]) age = IntegerField('Alter', validators=[NumberRange(min=0, max=120)]) gender = SelectField('Geschlecht', choices=[('m', 'Männlich'), ('w', 'Weiblich')])

WTForms bietet eine Vielzahl von Feldtypen für verschiedene Eingabetypen – von Text über Zahlen bis zu Datumsauswahl und Auswahllisten.

Wichtige Feldtypen

Feld HTML-Tag Beschreibung
StringField <input type="text"> Text-Eingabe
PasswordField <input type="password"> Passwort-Eingabe
TextAreaField <textarea> Mehrzeilige Texteingabe
IntegerField <input type="number"> Ganzzahlen
FloatField <input type="number" step="any"> Gleitkommazahlen
BooleanField <input type="checkbox"> Checkbox (True/False)
SelectField <select> Dropdown-Auswahl
RadioField <input type="radio"> Radio-Buttons
DateField <input type="date"> Datum (datetime.date)
DateTimeField <input type="datetime-local"> Datum + Uhrzeit
FileField <input type="file"> Datei-Upload (mit Flask-WTF)
SubmitField <input type="submit"> Absende-Button
HiddenField <input type="hidden"> Verstecktes Feld
Beispiele
# forms.py – verschiedene Feldtypen
class ProfileForm(FlaskForm):
bio = TextAreaField('Biografie', validators=[Length(max=500)])
birthday = DateField('Geburtstag', format='%Y-%m-%d')
notifications = BooleanField('Benachrichtigungen aktivieren')
role = SelectField('Rolle', choices=[
('admin', 'Administrator'),
('user', 'Benutzer'),
('guest', 'Gast')
], default='user')
color = RadioField('Farbe', choices=[
('red', 'Rot'),
('green', 'Grün'),
('blue', 'Blau')
])
Tipp: Für SelectField können die choices auch dynamisch aus einer Datenbank geladen werden – z.B. aus einer SQLAlchemy-Query.

Validierung – Daten prüfen mit Validatoren

DataRequired · Email · Length · Custom Validator
# Eingebaute Validatoren from wtforms.validators import DataRequired, Email, Length, NumberRange, EqualTo, Optional # Benutzerdefinierter Validator def validate_username(form, field): if field.data == 'admin': raise ValidationError('Benutzername nicht erlaubt')

Validatoren prüfen, ob die eingegebenen Daten bestimmten Regeln entsprechen. WTForms bietet eine Reihe eingebauter Validatoren und erlaubt benutzerdefinierte Validierungsfunktionen.

Wichtige Validatoren

Validator Beschreibung
DataRequired() Feld darf nicht leer sein
Optional() Feld ist optional (überspringt andere Validatoren)
Email() Prüft auf gültige Email-Adresse
Length(min, max) Prüft Länge von Strings
NumberRange(min, max) Prüft Zahlenbereich
EqualTo(fieldname) Prüft Gleichheit mit anderem Feld
Regexp(regex) Prüft mit regulärem Ausdruck
URL() Prüft auf gültige URL
AnyOf(values) Wert muss in Liste enthalten sein
NoneOf(values) Wert darf nicht in Liste enthalten sein
Beispiele
# forms.py mit Validatoren
from wtforms import StringField, PasswordField, SubmitField, ValidationError
from wtforms.validators import DataRequired, Length, Email, EqualTo, Regexp
def validate_username(form, field):
# Benutzerdefinierte Validierung
if field.data in ['admin', 'root', 'system']:
raise ValidationError('Dieser Benutzername ist reserviert')
def validate_password(form, field):
# Prüft, ob Passwort Zahl und Großbuchstabe enthält
if not any(c.isupper() for c in field.data):
raise ValidationError('Passwort muss mindestens einen Großbuchstaben enthalten')
if not any(c.isdigit() for c in field.data):
raise ValidationError('Passwort muss mindestens eine Zahl enthalten')
class SignupForm(FlaskForm):
username = StringField('Benutzername', validators=[
DataRequired(),
Length(min=3, max=20),
Regexp(r'^[a-zA-Z0-9_]+$', message='Nur Buchstaben, Zahlen und Unterstrich'),
validate_username
])
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Passwort', validators=[
DataRequired(),
Length(min=8),
validate_password
])
confirm = PasswordField('Passwort bestätigen', validators=[
DataRequired(),
EqualTo('password', message='Passwörter stimmen nicht überein')
])
submit = SubmitField('Registrieren')
Tipp: Benutzerdefinierte Validatoren können komplexe Geschäftslogik prüfen – z.B. ob ein Benutzername bereits in der Datenbank existiert.

CSRF-Schutz – Cross-Site Request Forgery verhindern

CSRFProtect · csrf_token · form.hidden_tag()
# app.py – CSRF-Schutz aktivieren from flask_wtf.csrf import CSRFProtect csrf = CSRFProtect(app) # In Template {{ form.csrf_token }} {{ form.hidden_tag() }}

CSRF-Schutz verhindert Cross-Site Request Forgery-Angriffe. Flask-WTF aktiviert den Schutz automatisch, wenn ein SECRET_KEY gesetzt ist.

Beispiele
# app.py – CSRF-Schutz konfigurieren
from flask_wtf.csrf import CSRFProtect
app.config['SECRET_KEY'] = 'ihr-geheimer-schluessel'
csrf = CSRFProtect(app)
# CSRF-Fehlerbehandlung (optional)
@app.errorhandler(CSRFError)
def handle_csrf_error(e):
return 'CSRF-Token ungültig', 400
# Template mit CSRF-Token
<form method="POST">
{{ form.hidden_tag() }} <!-- Enthält csrf_token -->
{{ form.name.label }} {{ form.name }}
{{ form.submit }}
</form>
# CSRF-Token manuell prüfen (falls nötig)
csrf.protect() # Wird automatisch von Flask-WTF aufgerufen
⚠️ Wichtig: Der SECRET_KEY muss sicher und geheim sein! Verwenden Sie für die Produktion eine zufällige, lange Zeichenfolge (z.B. secrets.token_hex(32)).

Datei-Upload – Dateien hochladen mit Flask

FileField · FileAllowed · FileRequired · werkzeug
# forms.py from flask_wtf.file import FileField, FileAllowed, FileRequired class UploadForm(FlaskForm): file = FileField('Datei', validators=[FileRequired(), FileAllowed(['jpg', 'png'])])

Datei-Upload wird mit FileField und den Validatoren FileRequired und FileAllowed realisiert. Die hochgeladene Datei wird über request.files abgerufen und gespeichert.

Beispiele
# forms.py
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed, FileRequired
class UploadForm(FlaskForm):
image = FileField('Bild', validators=[
FileRequired(message='Bitte wählen Sie eine Datei aus'),
FileAllowed(['jpg', 'jpeg', 'png', 'gif'], message='Nur Bilder erlaubt')
])
submit = SubmitField('Hochladen')
# app.py – Upload verarbeiten
import os
from werkzeug.utils import secure_filename
@app.route('/upload', methods=['GET', 'POST'])
def upload():
form = UploadForm()
if form.validate_on_submit():
file = form.image.data
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return f'Datei {filename} hochgeladen'
return render_template('upload.html', form=form)
# Template – enctype="multipart/form-data" ist wichtig!
<form method="POST" enctype="multipart/form-data">
{{ form.hidden_tag() }}
{{ form.image.label }} {{ form.image }}
{{ form.submit }}
</form>
Tipp: Verwenden Sie secure_filename() aus werkzeug.utils, um den Dateinamen zu bereinigen und Sicherheitslücken zu vermeiden. Konfigurieren Sie MAX_CONTENT_LENGTH für die maximale Dateigröße.

Rendering – Formulare in Templates anzeigen

form.field · form.errors · form.hidden_tag()
# Template mit Bootstrap-Stil {{ form.name.label(class_="form-label") }} {{ form.name(class_="form-control") }} {% if form.name.errors %} {% for error in form.name.errors %} <div class="text-danger">{{ error }}</div> {% endfor %} {% endif %}

Rendering zeigt Formularfelder und Fehlermeldungen im Template an. Mit form.hidden_tag() werden CSRF-Token eingefügt. Die Felder können mit CSS-Klassen gestaltet werden.

Beispiele
<!-- register.html – Komplettes Formular mit Bootstrap 5 -->
<form method="POST" action="{{ url_for('register') }}">
{{ form.hidden_tag() }}
<div class="mb-3">
{{ form.username.label(class_="form-label") }}
{{ form.username(class_="form-control") }}
{% if form.username.errors %}
{% for error in form.username.errors %}
<div class="text-danger">{{ error }}</div>
{% endfor %}
{% endif %}
</div>
<div class="mb-3">
{{ form.email.label(class_="form-label") }}
{{ form.email(class_="form-control", type="email") }}
{% if form.email.errors %}
{% for error in form.email.errors %}
<div class="text-danger">{{ error }}</div>
{% endfor %}
{% endif %}
</div>
{{ form.submit(class_="btn btn-primary") }}
</form>
# Alternative: Einfache Anzeige mit Bootstrap-Flask
{% from "bootstrap/form.html" import render_form %}
{{ render_form(form) }}
Tipp: Für eine noch einfachere Darstellung können Sie Erweiterungen wie Flask-Bootstrap oder Bootstrap-Flask verwenden, die automatisch Bootstrap-stilisierte Formulare generieren.

Flask Forms im Überblick

FlaskForm Basis-Klasse
Flask-WTF Formular
Fields Feldtypen
String, Integer, Select, etc.
Validators Validierungsregeln
DataRequired, Email, Length
CSRF Schutz vor XSRF
CSRFProtect
FileField Datei-Upload
FileRequired, FileAllowed
Rendering Template-Anzeige
form.field, form.errors

Quick Summary

FlaskForm
Formular-Klasse
StringField
Feldtypen
DataRequired
Validatoren
csrf_token
CSRF-Schutz
FileField
Datei-Upload
form.hidden_tag()
Rendering
form.validate_on_submit() · StringField(validators=[DataRequired()]) · {{ form.hidden_tag() }}