Flask WTF
Flask WTF
Release 0.9.5
Dan Jacob
1 Current Version 3
2 Features 5
3 User’s Guide 7
3.1 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.2 Quickstart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.3 Creating Forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.4 CSRF Protection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.5 Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4 API Documentation 15
4.1 Developer Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
5 Additional Notes 19
5.1 Upgrading to Newer Releases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
5.2 Flask-WTF Changelog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
5.3 Authors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.4 BSD License . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
i
ii
flask-wtf Documentation, Release 0.9.5
Contents 1
flask-wtf Documentation, Release 0.9.5
2 Contents
CHAPTER 1
Current Version
3
flask-wtf Documentation, Release 0.9.5
Features
5
flask-wtf Documentation, Release 0.9.5
6 Chapter 2. Features
CHAPTER 3
User’s Guide
This part of the documentation, which is mostly prose, begins with some background information about Flask-WTF,
then focuses on step-by-step instructions for getting the most out of Flask-WTF.
3.1 Installation
This part of the documentation covers the installation of Flask-WTF. The first step to using any software package is
getting it properly installed.
Once you have a copy of the source, you can embed it in your Python package, or install it into your site-packages
easily:
7
flask-wtf Documentation, Release 0.9.5
3.2 Quickstart
Eager to get started? This page gives a good introduction to Flask-WTF. It assumes you already have Flask-WTF
installed. If you do not, head over to the Installation section.
Flask-WTF provides your Flask application integration with WTForms. For example:
from flask_wtf import Form
from wtforms import StringField
from wtforms.validators import DataRequired
class MyForm(Form):
name = StringField('name', validators=[DataRequired()])
Note: From version 0.9.0, Flask-WTF will not import anything from wtforms, you need to import fields from wtforms.
In addition, a CSRF token hidden field is created automatically. You can render this in your template:
<form method="POST" action="/">
{{ form.csrf_token }}
{{ form.name.label }} {{ form.name(size=20) }}
<input type="submit" value="Go">
</form>
However, in order to create valid XHTML/HTML the Form class has a method hidden_tag which renders any hidden
fields, including the CSRF field, inside a hidden DIV tag:
<form method="POST" action="/">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name(size=20) }}
<input type="submit" value="Go">
</form>
Note that you don’t have to pass request.form to Flask-WTF; it will load automatically. And the convenience
validate_on_submit will check if it is a POST request and if it is valid.
Heading over to Creating Forms to learn more skills.
Without any configuration, the Form will be a session secure form with csrf protection. We encourage you do nothing.
But if you want to disable the csrf protection, you can pass:
form = Form(csrf_enabled=False)
If you want to disable it globally, which you really shouldn’t. But if you insist, it can be done with the configuration:
WTF_CSRF_ENABLED = False
In order to generate the csrf token, you must have a secret key, this is usually the same as your Flask app secret key. If
you want to use another secret key, config it:
WTF_CSRF_SECRET_KEY = 'a random string'
Flask-WTF provides you a FileField to handle file uploading, it will automatically draw data from
flask.request.files if the form is posted. The data attribute of FileField will be an instance of Werkzeug
FileStorage.
For example:
from werkzeug import secure_filename
from flask_wtf.file import FileField
class PhotoForm(Form):
photo = FileField('Your photo')
Note: Remember to set the enctype of your HTML form to multipart/form-data, which means:
<form action="/upload/" method="POST" enctype="multipart/form-data">
....
</form>
More than that, Flask-WTF supports validation on file uploading. There are FileRequired and FileAllowed.
The FileAllowed works well with Flask-Uploads, for example:
class UploadForm(Form):
upload = FileField('image', validators=[
FileRequired(),
FileAllowed(images, 'Images only!')
])
It can work without Flask-Uploads too. You need to pass the extensions to FileAllowed:
class UploadForm(Form):
upload = FileField('image', validators=[
FileRequired(),
FileAllowed(['jpg', 'png'], 'Images only!')
])
Note: HTML5 widgets and fields are builtin of wtforms since 1.0.5. You should consider import them from wtforms
if possible.
We will drop html5 module in next release 0.9.3.
class LinkForm(Form):
url = URLField(validators=[url()])
3.3.4 Recaptcha
class SignupForm(Form):
username = TextField('Username')
recaptcha = RecaptchaField()
This comes together with a number of configuration, which you have to implement them.
Flask-WTF form is already protecting you from CSRF, you don’t have to worry about that. However, you have views
that contain no forms, and they still need protection.
For example, the POST request is sent by AJAX, but it has no form behind it. You can’t get the csrf token prior 0.9.0
of Flask-WTF. That’s why we created this CSRF for you.
3.4.2 Implementation
To enable CSRF protection for all your view handlers, you need to enable the CsrfProtect module:
from flask_wtf.csrf import CsrfProtect
CsrfProtect(app)
csrf = CsrfProtect()
def create_app():
app = Flask(__name__)
csrf.init_app(app)
Note: You need to setup a secret key for CSRF protection. Usually, this is the same as your Flask app SECRET_KEY.
If the template has a form, you don’t need to do any thing. It is the same as before:
But if the template has no forms, you still need a csrf token:
<form method="post" action="/">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
</form>
Whenever a CSRF validation fails, it will return a 400 response. You can customize the error response:
@csrf.error_handler
def csrf_error(reason):
return render_template('csrf_error.html', reason=reason), 400
We strongly suggest that you protect all your views from CSRF. But there is a chance that you might exclude some
view handlers, it can be done:
@csrf.exempt
@app.route('/foo', methods=('GET', 'POST'))
def my_handler():
# ...
return 'ok'
3.4.3 AJAX
Sending POST requests via AJAX is possible where there is no forms at all. This feature is only available since 0.9.0.
Assumimg you have done CsrfProtect(app), you can get the csrf token via {{ csrf_token() }}. This
method is available in every templates, that way you don’t have to worry if there are no forms for rendering the csrf
token field.
The suggested way is that you render the token in a <meta> tag:
<meta name="csrf-token" content="{{ csrf_token() }}">
We will take the <meta> way for example, the <script> way is far more easier, you don’t have to worry if there is
no example for it.
Whenever you send a AJAX POST request, add the X-CSRFToken for it:
var csrftoken = $('meta[name=csrf-token]').attr('content')
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken)
}
}
})
3.4.4 Troubleshooting
When you define your forms, if you make the mistake of importing Form from wtforms in-
stead of from flask.ext.wtf, most features besides CSRF protection will work (aside from
form.validate_on_submit()), but CSRF protection will fail. Upon submitting forms, you’ll get Bad
Request/CSRF token missing or incorrect (and the form.csrf_token in your template will
produce no output). The problem is in your broken import statements, not your configuration.
3.5 Configuration
The full list of configuration for Flask-WTF. Usually, you don’t need to configure any of them. It just works.
WTF_CSRF_ENABLED Disable/enable CSRF protection for forms. Default is True.
WTF_I18N_ENABLED Disable/enable I18N support. This should work together with Flask-Babel. Default is
True.
WTF_CSRF_HEADERS CSRF token HTTP headers checked. Default is [’X-CSRFToken’, ‘X-CSRF-Token’]
WTF_CSRF_SECRET_KEYA random string for generating CSRF token. Default is the same as SECRET_KEY.
WTF_CSRF_TIME_LIMITCSRF token expiring time. Default is 3600 seconds.
WTF_CSRF_SSL_STRICTStrictly protection on SSL. This will check the referrer, validate if it is from the same
origin. Default is True.
WTF_CSRF_METHODS CSRF protection on these request methods. Default is [’POST’, ‘PUT’, ‘PATCH’]
WTF_HIDDEN_TAG HTML tag name of the hidden tag wrapper. Default is div
HTML tag attributes of the hidden tag wrapper. Default is {‘style’: ‘display:none;’}
WTF_HIDDEN_TAG_ATTRS
3.5.2 Recaptcha
You have already learned these configuration at Recaptcha. This table is only designed for a convience.
RECAPTCHA_USE_SSL Enable/disable recaptcha through ssl. Default is False.
RE- required A public key.
CAPTCHA_PUBLIC_KEY
RE- required A private key.
CAPTCHA_PRIVATE_KEY
RECAPTCHA_OPTIONS optional A dict of configuration options.
https://www.google.com/recaptcha/admin/create
3.5. Configuration 13
flask-wtf Documentation, Release 0.9.5
API Documentation
If you are looking for information on a specific function, class or method, this part of the documentation is for you.
15
flask-wtf Documentation, Release 0.9.5
validate_csrf_data(data)
Check if the csrf data is valid.
Parameters data – the csrf string to be validated.
validate_on_submit()
Checks if form has been submitted and if so runs validate. This is a shortcut, equivalent to
form.is_submitted() and form.validate()
class flask_wtf.RecaptchaField(label=’‘, validators=None, **kwargs)
class flask_wtf.Recaptcha(message=None)
Validates a ReCaptcha.
class flask_wtf.RecaptchaWidget
class flask_wtf.file.FileField(label=None, validators=None, filters=(), description=’‘, id=None,
default=None, widget=None, render_kw=None, _form=None,
_name=None, _prefix=’‘, _translations=None, _meta=None)
Werkzeug-aware subclass of wtforms.FileField
Provides a has_file() method to check if its data is a FileStorage instance with an actual file.
has_file()
Return True iff self.data is a FileStorage with file data
class flask_wtf.file.FileAllowed(upload_set, message=None)
Validates that the uploaded file is allowed by the given Flask-Uploads UploadSet.
Parameters
• upload_set – A list/tuple of extention names or an instance of
flask.ext.uploads.UploadSet
• message – error message
You can also use the synonym file_allowed.
class flask_wtf.file.FileRequired(message=None)
Validates that field has a file.
Parameters message – error message
You can also use the synonym file_required.
class flask_wtf.html5.SearchInput(input_type=None)
Renders an input with type “search”.
class flask_wtf.html5.SearchField(label=None, validators=None, filters=(), description=’‘,
id=None, default=None, widget=None, render_kw=None,
_form=None, _name=None, _prefix=’‘, _translations=None,
_meta=None)
Represents an <input type="search">.
class flask_wtf.html5.URLInput(input_type=None)
Renders an input with type “url”.
class flask_wtf.html5.URLField(label=None, validators=None, filters=(), description=’‘, id=None,
default=None, widget=None, render_kw=None, _form=None,
_name=None, _prefix=’‘, _translations=None, _meta=None)
Represents an <input type="url">.
class flask_wtf.html5.EmailInput(input_type=None)
Renders an input with type “email”.
class flask_wtf.csrf.CsrfProtect(app=None)
Enable csrf protect for Flask.
Register it with:
app = Flask(__name__)
CsrfProtect(app)
If you need to send the token via AJAX, and there is no form:
<meta name="csrf_token" content="{{ csrf_token() }}" />
You can grab the csrf token with JavaScript, and send the token together.
error_handler(view)
A decorator that set the error response handler.
It accepts one parameter reason:
@csrf.error_handler
def csrf_error(reason):
return render_template('error.html', reason=reason)
@csrf.exempt
@app.route('/some-view', methods=['POST'])
def some_view():
return
flask_wtf.csrf.generate_csrf(secret_key=None, time_limit=None)
Generate csrf token code.
Parameters
• secret_key – A secret key for mixing in the token, default is Flask.secret_key.
• time_limit – Token valid in the time limit, default is 3600s.
flask_wtf.csrf.validate_csrf(data, secret_key=None, time_limit=None)
Check if the given data is a valid csrf token.
Parameters
• data – The csrf token value to be checked.
• secret_key – A secret key for mixing in the token, default is Flask.secret_key.
• time_limit – Check if the csrf token is expired. default is True.
Additional Notes
Flask-WTF itself is changing like any software is changing over time. Most of the changes are the nice kind, the kind
where you don’t have to change anything in your code to profit from a new release.
However every once in a while there are changes that do require some changes in your code or there are changes that
make it possible for you to improve your own code quality by taking advantage of new features in Flask-WTF.
This section of the documentation enumerates all the changes in Flask-WTF from release to release and how you can
change your code to have a painless updating experience.
If you want to use the easy_install command to upgrade your Flask-WTF installation, make sure to pass it the -U
parameter:
$ pip install -U Flask-WTF
Dropping the imports of wtforms is a big change, it may be lots of pain for you, but the imports are hard to maintain.
Instead of importing Fields from Flask-WTF, you need to import them from the original wtforms:
from wtforms import TextField
Configuration name of CSRF_ENABLED is changed to WTF_CSRF_ENABLED. There is a chance that you don’t need
to do anything if you haven’t set any configuration.
This version has many more features, if you don’t need them, they will not break any code of yours.
19
flask-wtf Documentation, Release 0.9.5
Released 2015/01/21
• Use the new reCAPTCHA API via #164.
Released 2014/11/16
• Add configuration: WTF_CSRF_HEADERS via #159.
• Support customize hidden tags via #150.
• And many more bug fixes
Released 2014/09/03
• Update translation for reCaptcha via #146.
Released 2014/08/26
• Update RECAPTCHA API SERVER URL via #145.
• Update requirement Werkzeug>=0.9.5
• Fix CsrfProtect exempt for blueprints via #143.
Released 2014/07/16
• Add configuration: WTF_CSRF_METHODS
• Support WTForms 2.0 now
• Fix csrf validation without time limit (time_limit=False)
• CSRF exempt supports blueprint #111.
Released 2014/03/21
• csrf_token for all template types #112.
• Make FileRequired a subclass of InputRequired #108.
Released 2013/12/20
• Bugfix for csrf module when form has a prefix
• Compatible support for wtforms2
• Remove file API for FileField
Released 2013/10/02
• Fix validation of recaptcha when app in testing mode #89.
• Bugfix for csrf module #91
Released 2013/9/11
• Upgrade wtforms to 1.0.5.
• No lazy string for i18n #77.
• No DateInput widget in html5 #81.
• PUT and PATCH for CSRF #86.
Released 2013/8/21
This is a patch version for backward compitable for Flask<0.10 #82.
Released 2013/8/15
• Add i18n support (issue #65)
• Use default html5 widgets and fields provided by wtforms
• Python 3.3+ support
• Redesign form, replace SessionSecureForm
• CSRF protection solution
• Drop wtforms imports
• Fix recaptcha i18n support
• Fix recaptcha validator for python 3
• More test cases, it’s 90%+ coverage now
• Redesign documentation
Released 2013/3/28
• Recaptcha Validator now returns provided message (issue #66)
• Minor doc fixes
• Fixed issue with tests barking because of nose/multiprocessing issue.
Released 2013/3/13
• Update documentation to indicate pending deprecation of WTForms namespace facade
• PEP8 fixes (issue #64)
• Fix Recaptcha widget (issue #49)
Initial development by Dan Jacob and Ron Duplain. 0.8.2 and prior there was not a change log.
5.3 Authors
5.3.1 Contributors
Copyright (c) 2010 by Dan Jacob. Copyright (c) 2013 - 2014 by Hsiaoming Yang.
Some rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
following conditions are met:
• Redistributions of source code must retain the above copyright notice, this list of conditions and the following
disclaimer.
• Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the follow-
ing disclaimer in the documentation and/or other materials provided with the distribution.
• The names of the contributors may not be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, IN-
CIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSI-
NESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CON-
TRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAM-
AGE.
f
flask_wtf, 9
flask_wtf.csrf, 11
flask_wtf.file, 9
flask_wtf.html5, 16
flask_wtf.recaptcha, 10
25
flask-wtf Documentation, Release 0.9.5
C R
CsrfProtect (class in flask_wtf.csrf), 17 RangeInput (class in flask_wtf.html5), 17
Recaptcha (class in flask_wtf), 16
D RecaptchaField (class in flask_wtf), 16
DecimalField (class in flask_wtf.html5), 17 RecaptchaWidget (class in flask_wtf), 16
DecimalRangeField (class in flask_wtf.html5), 17
S
E SearchField (class in flask_wtf.html5), 16
EmailField (class in flask_wtf.html5), 16 SearchInput (class in flask_wtf.html5), 16
EmailInput (class in flask_wtf.html5), 16
error_handler() (flask_wtf.csrf.CsrfProtect method), 17 T
exempt() (flask_wtf.csrf.CsrfProtect method), 18 TelField (class in flask_wtf.html5), 17
TelInput (class in flask_wtf.html5), 17
F
FileAllowed (class in flask_wtf.file), 16 U
FileField (class in flask_wtf.file), 16 URLField (class in flask_wtf.html5), 16
FileRequired (class in flask_wtf.file), 16 URLInput (class in flask_wtf.html5), 16
flask_wtf (module), 9, 15
flask_wtf.csrf (module), 11, 17 V
flask_wtf.file (module), 9, 16 validate_csrf() (in module flask_wtf.csrf), 18
flask_wtf.html5 (module), 16 validate_csrf_data() (flask_wtf.Form method), 15
flask_wtf.recaptcha (module), 10 validate_on_submit() (flask_wtf.Form method), 16
Form (class in flask_wtf), 15
G
generate_csrf() (in module flask_wtf.csrf), 18
H
has_file() (flask_wtf.file.FileField method), 16
hidden_tag() (flask_wtf.Form method), 15
I
IntegerField (class in flask_wtf.html5), 17
IntegerRangeField (class in flask_wtf.html5), 17
is_submitted() (flask_wtf.Form method), 15
N
NumberInput (class in flask_wtf.html5), 17
27