Contents

Working with Forms

Handling forms is a common requirement in web applications, whether it’s for user registration, login, or collecting feedback. Flask makes working with forms straightforward, and using Flask-WTF (Flask extension for working with forms) enhances the process by providing tools for form validation and protection against common security risks.

Creating and Handling HTML Forms in Flask

Flask allows you to create and process HTML forms using the standard form elements in HTML. Here’s a basic example:

Step 1: Creating a Simple HTML Form

Let’s say you want to create a basic contact form. You would start by creating an HTML file called contact.html in your templates directory:

				
					<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Contact Us</title>
</head>
<body>
    <h1>Contact Us</h1>
    <form action="/contact" method="POST">
        <label for="name">Name:</label><br>
        <input type="text" id="name" name="name"><br><br>

        <label for="email">Email:</label><br>
        <input type="email" id="email" name="email"><br><br>

        <label for="message">Message:</label><br>
        <textarea id="message" name="message"></textarea><br><br>

        <input type="submit" value="Submit">
    </form>
</body>
</html>


				
			

Step 2: Handling the Form Submission in Flask

In your app.py, you would create a route to handle the form submission:

				
					from flask import Flask, request, render_template

app = Flask(__name__)

@app.route('/contact', methods=['GET', 'POST'])
def contact():
    if request.method == 'POST':
        name = request.form['name']
        email = request.form['email']
        message = request.form['message']
        # Process the data (e.g., save to a database or send an email)
        return f"Thank you, {name}! Your message has been received."
    return render_template('contact.html')

if __name__ == '__main__':
    app.run(debug=True)


				
			

In this example:

  • The form’s action attribute points to the /contact route, and the method is POST.
  • The Flask route handles both GET and POST requests. If the method is POST, it processes the form data; otherwise, it just displays the form.

Validating Form Data Using Flask-WTF

Flask-WTF is a Flask extension that simplifies form validation and helps protect your forms from CSRF (Cross-Site Request Forgery) attacks.

Step 1: Install Flask-WTF

To get started, you’ll need to install Flask-WTF:

				
					pip install Flask-WTF


				
			

Step 2: Creating a Form Class with Flask-WTF

Create a form class in forms.py using Flask-WTF:

				
					from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, SubmitField
from wtforms.validators import DataRequired, Email

class ContactForm(FlaskForm):
    name = StringField('Name', validators=[DataRequired()])
    email = StringField('Email', validators=[DataRequired(), Email()])
    message = TextAreaField('Message', validators=[DataRequired()])
    submit = SubmitField('Submit')


				
			

Step 3: Integrating the Form with Your Flask App

In app.py, modify the contact route to use the ContactForm class:

				
					from flask import Flask, render_template, flash, redirect, url_for
from forms import ContactForm

app = Flask(__name__)
app.secret_key = 'your_secret_key'

@app.route('/contact', methods=['GET', 'POST'])
def contact():
    form = ContactForm()
    if form.validate_on_submit():
        name = form.name.data
        email = form.email.data
        message = form.message.data
        # Process the data (e.g., save to a database or send an email)
        flash(f"Thank you, {name}! Your message has been received.", 'success')
        return redirect(url_for('contact'))
    return render_template('contact.html', form=form)

if __name__ == '__main__':
    app.run(debug=True)


				
			

Step 4: Updating the HTML Template to Use Flask-WTF

Modify your contact.html to integrate with the Flask-WTF form:

				
					<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Contact Us</title>
</head>
<body>
    <h1>Contact Us</h1>

    {% with messages = get_flashed_messages(with_categories=true) %}
      {% if messages %}
        {% for category, message in messages %}
          <div class="alert alert-{{ category }}">{{ message }}</div>
        {% endfor %}
      {% endif %}
    {% endwith %}

    <form method="POST" action="{{ url_for('contact') }}">
        {{ form.hidden_tag() }}
        <div>
            {{ form.name.label }}<br>
            {{ form.name(size=32) }}<br>
            {% for error in form.name.errors %}
                <span style="color: red;">[{{ error }}]</span>
            {% endfor %}
        </div>
        <div>
            {{ form.email.label }}<br>
            {{ form.email(size=32) }}<br>
            {% for error in form.email.errors %}
                <span style="color: red;">[{{ error }}]</span>
            {% endfor %}
        </div>
        <div>
            {{ form.message.label }}<br>
            {{ form.message(rows=5, cols=40) }}<br>
            {% for error in form.message.errors %}
                <span style="color: red;">[{{ error }}]</span>
            {% endfor %}
        </div>
        <div>
            {{ form.submit() }}
        </div>
    </form>
</body>
</html>


				
			

In this template:

  • {{ form.hidden_tag() }} generates hidden fields necessary for CSRF protection.
  • Form fields like {{ form.name(size=32) }} generate the actual input elements, and validation errors are displayed using {% for error in form.field_name.errors %}.

Handling Form Submissions and Displaying Validation Errors

When users submit a form, Flask-WTF makes it easy to handle the submission and show any validation errors.

  • Validation:
    When the form is submitted, validate_on_submit() checks if all the fields meet the validators’ requirements. If not, it returns False, and the form is re-rendered with error messages.

  • Displaying Errors:
    In the template, errors are displayed next to the corresponding fields, helping users correct their input.

Redirecting Users and Displaying Flash Messages

After processing a form submission, it’s often a good idea to redirect the user to another page (or back to the form) and display a confirmation message.

  • Redirecting:
    Use redirect() to send the user to another route after form submission:

				
					return redirect(url_for('contact'))


				
			
  • Flash Messages:
    Flash messages allow you to display one-time messages to the user, like “Thank you for your submission!” To flash a message, use the flash() function:
				
					flash(f"Thank you, {name}! Your message has been received.", 'success')


				
			

In your template, you can display these messages using the following block:

				
					{% with messages = get_flashed_messages(with_categories=true) %}
  {% if messages %}
    {% for category, message in messages %}
      <div class="alert alert-{{ category }}">{{ message }}</div>
    {% endfor %}
  {% endif %}
{% endwith %}


				
			

This code will display flash messages styled according to the category (like ‘success’, ‘error’, etc.).

Summary

Working with forms in Flask is straightforward, especially when using Flask-WTF. You can create and handle HTML forms, validate form data, display validation errors, and provide feedback to users with flash messages. This setup makes your web applications more interactive and user-friendly.