This video is available to students only

Rendering & Processing a Form

Using WTForms

As we've seen, manually writing out logic for rendering the form and validations manually for each form in a complex SaaS application would quickly become tedious. WTForms is a Python library that helps us handle rendering form inputs, validation, editing data, and CSRF protection.

In the last chapter we used SQLAlchemy to provide us with a more "Python-ic" way to manage our database schema and querying. WTForms similarly provides a "Python-ic" abstraction for forms and form fields.

We're going to go back and convert our "New Product" form to use WTForms.

To start with WTForms, add the Flask extension for WTForms Flask-WTF your requirements.txt file and then install it within your virtual environment. This will also install the actual WTForms library as well.

(env) $ pip install -r requirements.txt

Then create a file in the yumroad folder for us to store our form definitions called forms.py. This file will be similar to models.py in that it's a collection of classes where we declare the fields we want in our forms or models. You might see this pattern referred to as declarative class definitions.

If you see an error message about needing a secret key, you may need to add WTF_CSRF_ENABLED = False to your BaseConfig in yumroad/config.py depending on which version of Flask you install. We will enable CSRF later on in this chapter

Creating a product with a form

Our product catalog needs a way for our users to create products, and the two fields we have right now are one for the name and description, so our form should also contain those two fields.

Our first step to creating a form will be to create a class to define the form. In our models file, the classes inherit from a base model from SQLAlchemy (db.Model). Our form classes will similarly inherit from a base class named FlaskForm provided by flask_wtf.

from flask_wtf import FlaskForm

class ProductForm(FlaskForm):
    # our fields will be declared here
    pass

The next step is to declare the fields that this form will use. WTForms defines a set of fields for us to use, here are some of the common fields. A full list is available on the WTForms documentation.

NameTypeRendered As
StringFieldStringtext input
TextAreaFieldStringtextarea input
DateFielddatetime.datetimeA text input for a formatted date string
BooleanFieldBooleanA checkbox input
SelectFieldStringA select input
FileFieldDataA file upload field

We know that both of the fields we'll want our users to input are strings, but since the product description will be longer than the name, we want to render a textarea input for the description and a text input for the name.

To declare a field, we will import the field from wtforms.field and then initialize them with the name of the field that we'd like to display to users.

from flask_wtf import FlaskForm

from wtforms.fields import StringField, SubmitField

class ProductForm(FlaskForm):
    name = StringField('Name')
    description = StringField('Description')
    submit = SubmitField('Create Product')

To add in validations to ensure the input matches certain criteria, we can import validators from wtforms.validators and pass a list of validators into the second argument to form fields. WTForms provides us with many validators by default, here is a list of some of the more commonly used ones:

No discussions yet