The Flask-WTF documentation says:
Flask-WTF provides you with a FileField for handling file uploads; it automatically outputs data from flask.request.files if the form is submitted. The FileField data attribute will be an instance of Werkzeug FileStorage.
However, when I use FileField , the data attribute after publishing is not a FileStorage object. Instead, it is either None (if I define my form using enctype="multipart/form-data" , as suggested in the documentation), or the file name as a string (if I do not define enctype ).
Here is the corresponding Jinja2 template:
{% from "_form.html" import render_field %} {% block body %} <section class="page-width-container" id="offset-content"> <div id="utility-box"> <h1 class="utility-header">Settings</h1> {{ message }} <form action="/settings" method="post" enctype="multipart/form-data"> {{ render_field(form.photo) }} <input type="submit" class="form-action" value="Save" /> </form> </div> </section> {% endblock %}
Macro _form.html:
{% macro render_field(field) %} <div class="field"> {{ field.label }} <span class="form-input">{{ field()|safe }}</span> <div class="clear"></div> {% if field.errors %} <ul class="errors"> {% for error in field.errors %} <li>{{ error }}</li> {% endfor %} </ul> {% endif %} </div> {% endmacro %}
And here is Python:
from flask import Blueprint, render_template, request from flask.ext.wtf import Form from flask.ext.wtf.file import FileField, FileRequired settings_bp = Blueprint('settings', __name__) class SettingsForm(Form): photo = FileField('Photo', validators=[ FileRequired('no file!'), ]) @settings_bp.route('/settings', methods=['GET', 'POST']) def login(): form = SettingsForm(request.form) form.validate_on_submit() print(type(form.photo.data)) return render_template('settings.html', form=form, message=form.photo.data)
With the enctype attribute in the form element, the printed type is NoneType ; without the enctype attribute enctype printed unicode type. A FileStorage object advertised by documentation.