Python Flask:完整实现
在上篇文章里,我们使用扩展简化了文件上传的步骤。这次使用Flask-WTF来增强表单功能:处理表单验证,显示错误信息。因为同时使用Flask-Uploads,上传部分的实现见前两篇文章。
使用Flask-WTF
flask_wtf是flask框架的表单验证模块,可以很方便生成表单,也可以当做json数据交互的验证工具,支持热插拔。
初始化
为CSRF保护创建SECRET_KEY设置:
app.config['SECRET_KEY'] = 'a random string'
创建表单
使用Flask-WTF提供的FileField字段以及FileRequired、FileAllowed验证函数
from flask_wtf.file import FileField, FileRequired, FileAllowed
可以传入错误信息:
photo = FileField(u'图片上传', validators=[ FileAllowed(photos, u'只能上传图片!'), FileRequired(u'文件未选择!') ])
这里FileAllowed()的第一个参数是使用Flask-Uploads设置的set名称,如果不使用Flask-Uploads,可以替换成文件后缀组成的列表,比如['jpg', 'png']。
在模板中渲染错误信息
{% for error in form.field.errors %} {{ error }} {% endfor %}
这里面的field是字段名称,比如上面的photo。
获取文件
文件数据不再从request对象获取,而是使用data方法获取:
filename = photos.save(form.photo.data)
完整实现
这次把HTML代码放在了单独的文件,效果仍然和之前两个版本相同。
upload.py:
# -*- coding: utf-8 -*- import os from flask import Flask, render_template from flask_uploads import UploadSet, configure_uploads, IMAGES, patch_request_class from flask_wtf import FlaskForm from flask_wtf.file import FileField, FileRequired, FileAllowed from wtforms import SubmitField app = Flask(__name__) app.config['SECRET_KEY'] = 'I have a dream' app.config['UPLOADED_PHOTOS_DEST'] = os.getcwd() photos = UploadSet('photos', IMAGES) configure_uploads(app, photos) patch_request_class(app) # set maximum file size, default is 16MB class UploadForm(FlaskForm): photo = FileField(validators=[ FileAllowed(photos, u'只能上传图片!'), FileRequired(u'文件未选择!')]) submit = SubmitField(u'上传') @app.route('/', methods=['GET', 'POST']) def upload_file(): form = UploadForm() if form.validate_on_submit(): filename = photos.save(form.photo.data) file_url = photos.url(filename) else: file_url = None return render_template('index.html', form=form, file_url=file_url) if __name__ == '__main__': app.run()
模板文件:templates/index.html
<!DOCTYPE html> <title>Upload File</title> <h1>图片上传</h1> <form method="POST" enctype="multipart/form-data"> {{ form.hidden_tag() }} {{ form.photo }} {% for error in form.photo.errors %} <span style="color: red;">{{ error }}</span> {% endfor %} {{ form.submit }} </form> {% if file_url %} <br><img src="{{ file_url }}"> {% endif %}
Gist地址:https://gist.github.com/greyli/81d7e5ae6c9baf7f6cdfbf64e8a7c037
文件在数据库的表示
肯定有人想把文件存到数据库里,胡乱试了一通后发现没法子。甚至还有人想要把文件转换成base64编码存起来。这不是一心想把数据库玩坏么……数据库不是用来存文件的,文件应该放到硬盘里。数据库里只存储文件名。
存储文件名,然后使用的时候在视图函数里通过Flask-Uploads提供的url()方法获取URL,或是用Flask提供的send_from_directory()方法获取(参考这个系列第一篇文章)。
更正:出于文件管理的需要,不应该直接存储URL。
相关链接
Flask-WTF项目地址:https://github.com/lepture/flask-wtfFlask-WTF文件上传:http://flask-wtf.readthedocs.io/en/stable/form.html#module-flask_wtf.fileFlask-WTF文件上传字段及验证函数:http://flask-wtf.readthedocs.io/en/stable/api.html?highlight=upload#flask_wtf.file.FileFieldDemo Gist地址:https://gist.github.com/greyli/81d7e5ae6c9baf7f6cdfbf64e8a7c037
- - - - -
更多关于Flask和Web开发的原创内容,欢迎关注知乎专栏 - Hello, Flask!。