Forms

Handling forms in Flask involves capturing and processing data submitted by users through HTML forms. Flask provides several ways to work with form data, primarily using the request object and the Flask-WTF extension for more advanced form handling. Here's a detailed guide on how to handle forms in Flask:

Basic Form Handling with Flask

  1. Create the HTML Form: Define your form in an HTML template.
    <!-- templates/form.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Form Page</title>
    </head>
    <body>
        <h1>Submit Your Information</h1>
        <form action="/submit" method="post">
            <label for="name">Name:</label>
            <input type="text" id="name" name="name" required><br>
            <label for="email">Email:</label>
            <input type="email" id="email" name="email" required><br>
            <button type="submit">Submit</button>
        </form>
    </body>
    </html>
    
  2. Define the Route to Display the Form:
    # app/routes.py
    from flask import Blueprint, render_template, request, redirect, url_for
    
    bp = Blueprint('main', __name__)
    
    @bp.route('/form')
    def form():
        return render_template('form.html')
    
  3. Define the Route to Handle Form Submission:
    @bp.route('/submit', methods=['POST'])
    def submit():
        name = request.form['name']
        email = request.form['email']
        # Process the form data (e.g., save to database)
        return f'Thank you, {name}! We have received your email: {email}'
    

Advanced Form Handling with Flask-WTF

For more complex forms and validation, using the Flask-WTF extension is recommended. Flask-WTF integrates Flask with WTForms, providing form rendering, validation, and CSRF protection.

  1. Install Flask-WTF:
    pip install flask-wtf
    
  2. Create a Form Class: Define your form class using WTForms.
    # app/forms.py
    from flask_wtf import FlaskForm
    from wtforms import StringField, EmailField, SubmitField
    from wtforms.validators import DataRequired, Email
    
    class ContactForm(FlaskForm):
        name = StringField('Name', validators=[DataRequired()])
        email = EmailField('Email', validators=[DataRequired(), Email()])
        submit = SubmitField('Submit')
    
  3. Update Configuration: Add a secret key for CSRF protection in config.py.
    class Config:
        SECRET_KEY = 'you-will-never-guess'  # Or use os.environ.get('SECRET_KEY')
    
  4. Update the Route to Use the Form:
    # app/routes.py
    from .forms import ContactForm
    
    @bp.route('/contact', methods=['GET', 'POST'])
    def contact():
        form = ContactForm()
        if form.validate_on_submit():
            name = form.name.data
            email = form.email.data
            # Process the form data (e.g., save to database)
            return f'Thank you, {name}! We have received your email: {email}'
        return render_template('contact.html', form=form)
    
  5. Update the HTML Template to Use WTForms:
    <!-- templates/contact.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Contact Form</title>
    </head>
    <body>
        <h1>Contact Us</h1>
        <form method="post">
            {{ form.hidden_tag() }}
            <p>
                {{ form.name.label }}<br>
                {{ form.name(size=20) }}<br>
                {% for error in form.name.errors %}
                    <span style="color: red;">[{{ error }}]</span>
                {% endfor %}
            </p>
            <p>
                {{ form.email.label }}<br>
                {{ form.email(size=20) }}<br>
                {% for error in form.email.errors %}
                    <span style="color: red;">[{{ error }}]</span>
                {% endfor %}
            </p>
            <p>{{ form.submit() }}</p>
        </form>
    </body>
    </html>
    

Example Project: Form Handling

Project Structure:

my_flask_project/
├── app/
│   ├── __init__.py
│   ├── routes.py
│   ├── forms.py
│   ├── templates/
│   │   ├── form.html
│   │   └── contact.html
│   └── static/
├── run.py
└── config.py

app/forms.py:

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

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

app/routes.py:

from flask import Blueprint, render_template, request, redirect, url_for
from .forms import ContactForm

bp = Blueprint('main', __name__)

@bp.route('/form')
def form():
    return render_template('form.html')

@bp.route('/submit', methods=['POST'])
def submit():
    name = request.form['name']
    email = request.form['email']
    return f'Thank you, {name}! We have received your email: {email}'

@bp.route('/contact', methods=['GET', 'POST'])
def contact():
    form = ContactForm()
    if form.validate_on_submit():
        name = form.name.data
        email = form.email.data
        return f'Thank you, {name}! We have received your email: {email}'
    return render_template('contact.html', form=form)

run.py:

from app import create_app

app = create_app()

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

config.py:

class Config:
    SECRET_KEY = 'you-will-never-guess'

Summary

  • Basic Form Handling: Use the request object to access form data directly from the template.
  • Advanced Form Handling: Use Flask-WTF for form validation, CSRF protection, and rendering forms with WTForms.
  • CSRF Protection: Ensure your forms are secure with CSRF tokens, especially when using Flask-WTF.

By following these guidelines, you can effectively handle forms in your Flask applications, from simple data submissions to more complex interactions with validations and CSRF protection.