# Creating a form with WTForms
List of all code changes made in this lecture: https://diff-store.com/diff/section14__06_create_form_with_wtforms (opens new window)
To use WTForms in a Flask application, the easiest thing to do is install two dependencies:
WTForms will help us define the forms, and Flask-WTF will add extra functionality such as that to deal with CSRF tokens.
pip install wtforms pip install flask-wtf
# What is a CSRF token?
Cross-Site Request Forgery (CSRF) is a web security vulnerability. It allows an attacker to trick the browser into submitting a form that sends data to your application, without the user noticing it.
By including a unique token generated by the Flask server in all requests, it prevents the possibility of a CSRF attack because the attacker will need the server to generate the form, which comes with the whole HTML page and usually requires the user to log-in first.
# Create a WTForm Class
Let's create a new file called
movie_library/forms.py. There, we will create a Python class that represents our form.
from flask_wtf import FlaskForm class MovieForm(FlaskForm): pass
Note that the import is from
flask_wtf, as that will give the form CSRF protection (as long as the necessary field is included in the rendered HTML, more on that later).
# Define Form Fields
Next, we need to define our form fields. This form is for creating new movies, so it will only include four fields:
submit. The first two will be strings, and the
year will be an integer. The
submit field will be rendered as a button to submit the form.
Giving our fields appropriate types will do two things:
- Render the appropriate field type in HTML
- Make validation easier
from flask_wtf import FlaskForm from wtforms import IntegerField, StringField, SubmitField class MovieForm(FlaskForm): title = StringField("Title") director = StringField("Director") year = IntegerField("Year") submit = SubmitField("Add Movie")
With just this, we can go and render the form and it will work just fine!
However, one of the key benefits of WTForms is how easy it is to include validation in our forms. Let's look at that.
# Data Validation with WTForms
We will be including two types of validation in this form:
InputRequired, which makes it so the field cannot be empty when submitted
NumberRange, which makes it so the field must have a value between two provided numbers
WTForms ships with many more validators that you can use.
For now though, let's add the validation to our fields:
from flask_wtf import FlaskForm from wtforms import IntegerField, StringField, SubmitField from wtforms.validators import InputRequired, NumberRange class MovieForm(FlaskForm): title = StringField("Title", validators=[InputRequired()]) director = StringField("Director", validators=[InputRequired()]) year = IntegerField( "Year", validators=[ InputRequired(), NumberRange(min=1878, message="Please enter a year in the format YYYY."), ], ) submit = SubmitField("Add Movie")
I've made all three input fields required, and I've made the
year field have a minimum value of 1878, since that's when the first movie was released.
A few things to note:
validatorsis a keyword argument which takes a list of validator objects.
- Each validator object takes an optional
messagekeyword argument which will be displayed to users if the validation fails at that step.
- Validators are validated in the order in which they are defined, so that's why I put
Now that we've defined our form using WTForms, a few questions still remain!
- How do we render this form in our template?
- How do we receive form data?
- How do we validate the form data?
- If validation fails, how do we display the error messages to the user?
We will tackle all these questions over the next 2 lectures. Let's go!