Handling Forms in Flask using Flask-WTF

Flask provides a flask-WTF extension that makes form handling easy and structured. This article provides a detailed undertanding of:

  • What is Flask WTF?
  • Features of Flask WTF.
  • Create a simple contact Form using flask wtf extension
What is Flask WTF?

Flask WTF is a built-in module of flask which provides an alternative way of designing forms in flask.

Features of Flask WTF.
  • Provides global CSRF protection.
  • Provides Integration with web forms.
  • Features reCAPTCHA support.
  • Contains File upload that closely works with Flask Uploads More Flask WTF Features
Simple ContactForm using Flask.
Setup for using forms in Flask.

Environment set up
Install virtual environment (virtualenv)

Virtualenv is is a tool to create isolated Python environments.
It can be installed by using the following command;

pip install virtualenv
pip install virtualenv
pip install virtualenv

Enter fullscreen mode Exit fullscreen mode

Once it is installed, we can create the new virtual environment into a folder as given below.

$ mkdir flaskforms
$ cd flaskforms
$ virtualenv venv
$ mkdir flaskforms   
$ cd flaskforms
$ virtualenv venv
$ mkdir flaskforms $ cd flaskforms $ virtualenv venv

Enter fullscreen mode Exit fullscreen mode

In this example, am using windows. Activate the virtual environment as follows;

$ venv\scripts\activate
$ venv\scripts\activate 
$ venv\scripts\activate

Enter fullscreen mode Exit fullscreen mode

Install flask as follows;

pip install flask
pip install flask 
pip install flask

Enter fullscreen mode Exit fullscreen mode

To use the WT forms, we need to install the flask-wtf library which can be installed using pip installer as follows;

pip install flask-wtf
pip install flask-wtf 
pip install flask-wtf

Enter fullscreen mode Exit fullscreen mode

File structure.

\-- flaskforms
|-- forms.py
|-- main.py
\-- templates
|-- contact.html
\-- flaskforms
    |-- forms.py
    |-- main.py

    \-- templates
        |-- contact.html
\-- flaskforms |-- forms.py |-- main.py \-- templates |-- contact.html

Enter fullscreen mode Exit fullscreen mode

On form.py;
Import the Flask form as follows;

<span>from</span> <span>flask_wtf</span> <span>import</span> <span>FlaskForm</span>
<span>from</span> <span>flask_wtf</span> <span>import</span> <span>FlaskForm</span>
from flask_wtf import FlaskForm

Enter fullscreen mode Exit fullscreen mode

Then import field types from the WTForms package, and validators from the wtforms.validators package as follows:

<span>from</span> <span>flask_wtf</span> <span>import</span> <span>FlaskForm</span>
<span>#import required fields </span><span>from</span> <span>wtforms</span> <span>import</span> <span>StringField</span><span>,</span> <span>TextAreaField</span><span>,</span> <span>SubmitField</span>
<span>from</span> <span>wtforms.validators</span> <span>import</span> <span>DataRequired</span><span>,</span> <span>Email</span>
<span>from</span> <span>flask_wtf</span> <span>import</span> <span>FlaskForm</span>
<span>#import required fields </span><span>from</span> <span>wtforms</span> <span>import</span> <span>StringField</span><span>,</span> <span>TextAreaField</span><span>,</span> <span>SubmitField</span>
<span>from</span> <span>wtforms.validators</span> <span>import</span> <span>DataRequired</span><span>,</span> <span>Email</span>
from flask_wtf import FlaskForm #import required fields from wtforms import StringField, TextAreaField, SubmitField from wtforms.validators import DataRequired, Email

Enter fullscreen mode Exit fullscreen mode

Create a Contact form by initializing a class that inherits the FlaskForm object:

<span>class</span> <span>ContactForm</span><span>(</span><span>FlaskForm</span><span>):</span>
<span>class</span> <span>ContactForm</span><span>(</span><span>FlaskForm</span><span>):</span>
class ContactForm(FlaskForm):

Enter fullscreen mode Exit fullscreen mode

Our forms.py should be like this.

forms.py

<span>from</span> <span>flask_wtf</span> <span>import</span> <span>FlaskForm</span>
<span>#import required fields </span><span>from</span> <span>wtforms</span> <span>import</span> <span>StringField</span><span>,</span> <span>TextAreaField</span><span>,</span> <span>SubmitField</span>
<span>from</span> <span>wtforms.validators</span> <span>import</span> <span>DataRequired</span><span>,</span> <span>Email</span>
<span>#create instance of the for </span><span>class</span> <span>ContactForm</span><span>(</span><span>FlaskForm</span><span>):</span>
<span>#initializing the fields </span> <span>Firstname</span> <span>=</span> <span>StringField</span><span>(</span><span>'</span><span>firstname</span><span>'</span><span>,</span> <span>validators</span><span>=</span><span>[</span><span>DataRequired</span><span>()])</span>
<span>Lastname</span> <span>=</span> <span>StringField</span><span>(</span><span>'</span><span>lastname</span><span>'</span><span>,</span> <span>validators</span><span>=</span><span>[</span><span>DataRequired</span><span>()])</span>
<span>email</span> <span>=</span> <span>StringField</span><span>(</span><span>'</span><span>Password</span><span>'</span><span>,</span> <span>validators</span><span>=</span><span>[</span><span>DataRequired</span><span>(),</span><span>Email</span><span>()])</span>
<span>message</span> <span>=</span> <span>TextAreaField</span><span>(</span><span>'</span><span>message</span><span>'</span><span>,</span><span>validators</span><span>=</span><span>[</span><span>DataRequired</span><span>()])</span>
<span>send</span> <span>=</span> <span>SubmitField</span><span>(</span><span>'</span><span>Send</span><span>'</span><span>)</span>
<span>from</span> <span>flask_wtf</span> <span>import</span> <span>FlaskForm</span>
<span>#import required fields </span><span>from</span> <span>wtforms</span> <span>import</span> <span>StringField</span><span>,</span> <span>TextAreaField</span><span>,</span> <span>SubmitField</span>
<span>from</span> <span>wtforms.validators</span> <span>import</span> <span>DataRequired</span><span>,</span> <span>Email</span>

<span>#create instance of the for </span><span>class</span> <span>ContactForm</span><span>(</span><span>FlaskForm</span><span>):</span>
<span>#initializing the fields </span>    <span>Firstname</span> <span>=</span> <span>StringField</span><span>(</span><span>'</span><span>firstname</span><span>'</span><span>,</span> <span>validators</span><span>=</span><span>[</span><span>DataRequired</span><span>()])</span>
    <span>Lastname</span> <span>=</span> <span>StringField</span><span>(</span><span>'</span><span>lastname</span><span>'</span><span>,</span> <span>validators</span><span>=</span><span>[</span><span>DataRequired</span><span>()])</span>
    <span>email</span> <span>=</span> <span>StringField</span><span>(</span><span>'</span><span>Password</span><span>'</span><span>,</span> <span>validators</span><span>=</span><span>[</span><span>DataRequired</span><span>(),</span><span>Email</span><span>()])</span>
    <span>message</span> <span>=</span> <span>TextAreaField</span><span>(</span><span>'</span><span>message</span><span>'</span><span>,</span><span>validators</span><span>=</span><span>[</span><span>DataRequired</span><span>()])</span>
    <span>send</span> <span>=</span> <span>SubmitField</span><span>(</span><span>'</span><span>Send</span><span>'</span><span>)</span>
from flask_wtf import FlaskForm #import required fields from wtforms import StringField, TextAreaField, SubmitField from wtforms.validators import DataRequired, Email #create instance of the for class ContactForm(FlaskForm): #initializing the fields Firstname = StringField('firstname', validators=[DataRequired()]) Lastname = StringField('lastname', validators=[DataRequired()]) email = StringField('Password', validators=[DataRequired(),Email()]) message = TextAreaField('message',validators=[DataRequired()]) send = SubmitField('Send')

Enter fullscreen mode Exit fullscreen mode

We have created a contact form with four input fields(Firstname, Lastname, email and message) as well as send field which is a button.

Each input field consist of:

Type of input– WTforms has a large collection of input types. in this case we have imported StringField, TextAreaField, SubmitField input types.
Read more about input fields

Label– It is the default value to assign to the field, if no form or object input is provided.
For example ‘firstname’ is the label.

Validators-It is a restriction put on a field that must be met for the user’s input to be considered valid.

DataRequired validator ensures that the user fills in the form.

Email field has email validator Email() which validates email
Read more about Validators

Here’s a blueprint of what an input field should contain:

field = FieldType(
'label',
validators=[ExampleValidator(message="ERROR MESSAGE")],
)
field = FieldType(
    'label',
    validators=[ExampleValidator(message="ERROR MESSAGE")],
)
field = FieldType( 'label', validators=[ExampleValidator(message="ERROR MESSAGE")], )

Enter fullscreen mode Exit fullscreen mode

We now have a form class so we can create our flask app(main.py) and a route to render the ContactForm as follows:

<span>from</span> <span>flask</span> <span>import</span> <span>Flask</span><span>,</span> <span>render_template</span><span>,</span> <span>request</span>
<span>from</span> <span>forms</span> <span>import</span> <span>ContactForm</span>
<span>app</span> <span>=</span> <span>Flask</span><span>(</span><span>__name__</span><span>)</span>
<span>app</span><span>.</span><span>secret_key</span> <span>=</span> <span>'</span><span>development key</span><span>'</span>
<span>@app.route</span><span>(</span><span>'</span><span>/contact</span><span>'</span><span>,</span> <span>methods</span> <span>=</span> <span>[</span><span>'</span><span>GET</span><span>'</span><span>,</span> <span>'</span><span>POST</span><span>'</span><span>])</span>
<span>def</span> <span>contact</span><span>():</span>
<span>form</span><span>=</span><span>ContactForm</span><span>()</span>
<span>if</span> <span>form</span><span>.</span><span>validate_on_submit</span><span>():</span>
<span>return</span> <span>'</span><span> form submitted</span><span>'</span>
<span>return</span> <span>render_template</span><span>(</span><span>'</span><span>contact.html</span><span>'</span><span>,</span> <span>form</span><span>=</span><span>form</span><span>)</span>
<span>if</span> <span>__name__</span> <span>==</span> <span>'</span><span>__main__</span><span>'</span><span>:</span>
<span>app</span><span>.</span><span>run</span><span>(</span><span>debug</span> <span>=</span> <span>True</span><span>)</span>
<span>from</span> <span>flask</span> <span>import</span> <span>Flask</span><span>,</span> <span>render_template</span><span>,</span> <span>request</span>
<span>from</span> <span>forms</span> <span>import</span> <span>ContactForm</span>
<span>app</span> <span>=</span> <span>Flask</span><span>(</span><span>__name__</span><span>)</span>  

<span>app</span><span>.</span><span>secret_key</span> <span>=</span> <span>'</span><span>development key</span><span>'</span>  

<span>@app.route</span><span>(</span><span>'</span><span>/contact</span><span>'</span><span>,</span> <span>methods</span> <span>=</span> <span>[</span><span>'</span><span>GET</span><span>'</span><span>,</span> <span>'</span><span>POST</span><span>'</span><span>])</span>  
<span>def</span> <span>contact</span><span>():</span>  

    <span>form</span><span>=</span><span>ContactForm</span><span>()</span>

    <span>if</span> <span>form</span><span>.</span><span>validate_on_submit</span><span>():</span>
        <span>return</span> <span>'</span><span> form submitted</span><span>'</span>
    <span>return</span> <span>render_template</span><span>(</span><span>'</span><span>contact.html</span><span>'</span><span>,</span> <span>form</span><span>=</span><span>form</span><span>)</span>


<span>if</span> <span>__name__</span> <span>==</span> <span>'</span><span>__main__</span><span>'</span><span>:</span>  
   <span>app</span><span>.</span><span>run</span><span>(</span><span>debug</span> <span>=</span> <span>True</span><span>)</span>  
from flask import Flask, render_template, request from forms import ContactForm app = Flask(__name__) app.secret_key = 'development key' @app.route('/contact', methods = ['GET', 'POST']) def contact(): form=ContactForm() if form.validate_on_submit(): return ' form submitted' return render_template('contact.html', form=form) if __name__ == '__main__': app.run(debug = True)

Enter fullscreen mode Exit fullscreen mode

From the above code;

  • SECRET_KEY configuration variable is very important when working with flask WT forms as it uses it to protect web forms against a nasty attack called Cross-Site Request Forgery(CSRF).
  • Our contact route accepts both GET and POST requests.
  • Since we are using Flaskform base class to create a ContactForm routing is more simple.
  • validate_on_submit() detects if a request is both a POST request and a valid request.

We can now render our form on contact.html as follows:

<span><html></span>
<span><head></span>
<span><title></span>Handling flaskforms<span></title></span>
<span><link</span> <span>rel=</span><span>"stylesheet"</span> <span>href=</span><span>"static/css/style.css"</span><span>></span>
<span><body></span>
<span><div</span> <span>class=</span><span>"form"</span><span>></span>
<span><form</span> <span>method=</span><span>"POST"</span> <span>action=</span><span>""</span><span>></span>
{{form.csrf_token}}
{{form.firstname.label}}<span><br></span>
{{form.firstname}}
<span><br></span>
{{form.lastname.label}}<span><br></span>
{{form.lastname}}
<span><br></span>
{{form.email.label}}<span><br></span>
{{form.email}}
<span><br></span>
{{form.message.label}}<span><br></span>
{{form.message}}
<span><br><br></span>
{{form.send}}
<span></form></span>
<span></div></span>
<span></body></span>
<span></head></span>
<span></html></span>
<span><html></span>

<span><head></span>
    <span><title></span>Handling flaskforms<span></title></span>
    <span><link</span> <span>rel=</span><span>"stylesheet"</span> <span>href=</span><span>"static/css/style.css"</span><span>></span>

    <span><body></span>


<span><div</span> <span>class=</span><span>"form"</span><span>></span>
        <span><form</span> <span>method=</span><span>"POST"</span> <span>action=</span><span>""</span><span>></span>

            {{form.csrf_token}}

            {{form.firstname.label}}<span><br></span>
            {{form.firstname}}
            <span><br></span>
            {{form.lastname.label}}<span><br></span>
            {{form.lastname}}
            <span><br></span>
            {{form.email.label}}<span><br></span>
            {{form.email}}
            <span><br></span>
            {{form.message.label}}<span><br></span>
            {{form.message}}

            <span><br><br></span>
            {{form.send}}

        <span></form></span>
    <span></div></span>
    <span></body></span>
<span></head></span>
<span></html></span>
<html> <head> <title>Handling flaskforms</title> <link rel="stylesheet" href="static/css/style.css"> <body> <div class="form"> <form method="POST" action=""> {{form.csrf_token}} {{form.firstname.label}}<br> {{form.firstname}} <br> {{form.lastname.label}}<br> {{form.lastname}} <br> {{form.email.label}}<br> {{form.email}} <br> {{form.message.label}}<br> {{form.message}} <br><br> {{form.send}} </form> </div> </body> </head> </html>

Enter fullscreen mode Exit fullscreen mode

Now we have our form here:

Full source code

原文链接:Handling Forms in Flask using Flask-WTF

© 版权声明
THE END
喜欢就支持一下吧
点赞14 分享
The best things in life are free.
生活中最美好的事都是免费的
评论 抢沙发

请登录后发表评论

    暂无评论内容