NelsonLabs
Flask/Forms & User Input

Forms & User Input

Flask doesn't include form handling — that's where Flask-WTF (WTForms integration) comes in. It adds CSRF protection, validation, and HTML rendering.

Install Flask-WTF
bash
pip install flask-wtf
Forms with Flask-WTF
python
from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, SelectField, SubmitField
from wtforms.validators import DataRequired, Email, Length

app.config["SECRET_KEY"] = "your-secret-key"  # required for CSRF

class ContactForm(FlaskForm):
    name    = StringField("Name",    validators=[DataRequired(), Length(min=2, max=100)])
    email   = StringField("Email",   validators=[DataRequired(), Email()])
    course  = SelectField("Course",  choices=[("html", "HTML"), ("css", "CSS")])
    message = TextAreaField("Message", validators=[DataRequired(), Length(min=10)])
    submit  = SubmitField("Send")

@app.route("/contact", methods=["GET", "POST"])
def contact():
    form = ContactForm()
    if form.validate_on_submit():  # validates on POST only
        name    = form.name.data
        email   = form.email.data
        message = form.message.data
        send_email(name, email, message)
        flash("Message sent!", "success")
        return redirect(url_for("contact"))
    return render_template("contact.html", form=form)
Rendering forms in templates
html
<form method="POST">
  {{ form.hidden_tag() }}  {# CSRF token — required! #}

  <div>
    {{ form.name.label }}
    {{ form.name(placeholder="Your name") }}
    {% for error in form.name.errors %}
      <span class="error">{{ error }}</span>
    {% endfor %}
  </div>

  <div>
    {{ form.email.label }}
    {{ form.email() }}
    {% for error in form.email.errors %}
      <span class="error">{{ error }}</span>
    {% endfor %}
  </div>

  <div>{{ form.submit() }}</div>
</form>