Python Flask:完整实现

来自CloudWiki
跳转至: 导航搜索

在上篇文章里,我们使用扩展简化了文件上传的步骤。这次使用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!。