Build HTML Forms in a Flask App With Python and 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
To start with WTForms, add the Flask extension for WTForms
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 = Falseto your
yumroad/config.pydepending 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
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.
|FileField||Data||A 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: