Categories
Flask

Python Web Development with Flask — Form Validation and Template Inheritance

Spread the love

Flask is a simple web framework written in Python.

In this article, we’ll look at how to develop simple Python web apps with Flask.

Form Validation with WTForms

We can add form validation into our Flask app with the WTForms library.

To install the library, we run:

pip install wtforms

Then we can use it by writing:

from flask import Flask, request
from wtforms import Form, BooleanField, StringField, PasswordField, validators
app = Flask(__name__)

class RegistrationForm(Form):
    username = StringField('Username', [validators.Length(min=4, max=25)])
    email = StringField('Email Address', [validators.Length(min=6, max=35)])
    password = PasswordField('New Password', [
        validators.DataRequired(),
        validators.EqualTo('confirm', message='Passwords must match')
    ])
    confirm = PasswordField('Repeat Password')
    accept_tos = BooleanField('I accept the TOS', [validators.DataRequired()])

@app.route('/register', methods=['POST'])
def register():
    form = RegistrationForm(request.form)
    if request.method == 'POST':
        if form.validate():
            return 'thanks for registering'
        else:
            return 'registration failed'



We create the RegistrationForm class that extends the Form class from wtforms .

We add the fields in there with the built in constructors.

StringField creates a string field.

The first argument is the name.

The 2nd argument has the validation rules.

validators.length checks the length.

PasswordField creates a password field.

BooleanField creates a boolean field.

validators.DataRequired() lets us make a field required.

We can show fields and registration messages in our template by using a macro.

For example, we can write:

app.py

from flask import Flask, request, render_template
from wtforms import Form, BooleanField, StringField, PasswordField, validators
app = Flask(__name__)

class RegistrationForm(Form):
    username = StringField('Username', [validators.Length(min=4, max=25)])
    email = StringField('Email Address', [validators.Length(min=6, max=35)])
    password = PasswordField('New Password', [
        validators.DataRequired(),
        validators.EqualTo('confirm', message='Passwords must match')
    ])
    confirm = PasswordField('Repeat Password')
    accept_tos = BooleanField('I accept the TOS', [validators.DataRequired()])

@app.route('/register', methods=['GET','POST'])
def register():
    form = RegistrationForm(request.form)
    if request.method == 'POST' and form.validate():
        return 'thanks for registering'
    return render_template('register.html', form=form)

templates/_formhelpers.html

{% macro render_field(field) %}
  <dt>{{ field.label }}
  <dd>{{ field(**kwargs)|safe }}
  {% if field.errors %}
    <ul class=errors>
    {% for error in field.errors %}
      <li>{{ error }}</li>
    {% endfor %}
    </ul>
  {% endif %}
  </dd>
{% endmacro %}

templates/register.html

{% from "_formhelpers.html" import render_field %}
<form method=post>
  <dl>
    {{ render_field(form.username) }}
    {{ render_field(form.email) }}
    {{ render_field(form.password) }}
    {{ render_field(form.confirm) }}
    {{ render_field(form.accept_tos) }}
  </dl>
  <p><input type=submit value=Register>
</form>

We create the render_field macro that we use with the register.html template.

The field function renders the field.

field.errors renders the errors.

In the register.html file, we call render_field to render the fields with the errors with the render_field macro.

Template Inheritance

We can inherit from a base template so we can have shared items in there.

For example, we can write:

app.py

from flask import Flask, render_template
app = Flask(__name__)

@app.route('/')
def register():
    return render_template('index.html')

templates/layout.html

<!doctype html>
<html>
  <head>
    {% block head %}
    <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
    <title>{% block title %}{% endblock %} - My Webpage</title>
    {% endblock %}
  </head>
  <body>
    <div id="content">{% block content %}{% endblock %}</div>
    <div id="footer">
      {% block footer %}
      &copy; Copyright 2010 by <a href="http://domain.invalid/">you</a>.
      {% endblock %}
    </div>
  </body>
</html>

templates/index.html

{% extends "layout.html" %}
{% block title %}Index{% endblock %}
{% block head %}
  {{ super() }}
  <style type="text/css">
    .important { color: #336699; }
  </style>
{% endblock %}
{% block content %}
  <h1>Index</h1>
  <p class="important">
    Welcome on my awesome homepage.
{% endblock %}

static/style.css

body {
    font-size: 20px;
}

In layout.html , we add the blocks with the block keyword.

Then we override them with our own content with the index.html template.

Conclusion

We can add form validation and base templates with Flask.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *