Flask文件上傳(三):完整實現
在上篇文章里,我們使用擴展簡化了文件上傳的步驟。這次使用Flask-WTF來增強表單功能:處理表單驗證,顯示錯誤信息。因為同時使用Flask-Uploads,上傳部分的實現見前兩篇文章。
Flask文件上傳系列目錄
- Flask文件上傳(一):原生實現
- Flask文件上傳(二):使用擴展實現
- Flask文件上傳(三):完整實現
- Flask文件上傳(四):文件管理與多文件上傳
- Flask文件上傳(五):拖拽上傳和進度條
使用Flask-WTF
如果你對Flask-WTF還不熟悉,可以看看之前的幾篇文章,或是讀讀文檔。
1、初始化
為CSRF保護創建SECRET_KEY設置:
app.config[SECRET_KEY] = a random stringn
2、創建表單
使用Flask-WTF提供的FileField欄位以及FileRequired、FileAllowed驗證函數
from flask_wtf.file import FileField, FileRequired, FileAllowedn
可以傳入錯誤信息:
photo = FileField(u圖片上傳, validators=[n FileAllowed(photos, u只能上傳圖片!), n FileRequired(u文件未選擇!)n])n
這裡FileAllowed()的第一個參數是使用Flask-Uploads設置的set名稱,如果不使用Flask-Uploads,可以替換成文件後綴組成的列表,比如[jpg, png]。
3、在模板中渲染錯誤信息
{% for error in form.field.errors %}n {{ error }}n{% endfor %}n
這裡面的field是欄位名稱,比如上面的photo。
4、獲取文件
文件數據不再從request對象獲取,而是使用data方法獲取:
filename = photos.save(form.photo.data)n
完整實現
這次把HTML代碼放在了單獨的文件,效果仍然和之前兩個版本相同。
upload.py
# -*- coding: utf-8 -*-nimport osnnfrom flask import Flask, render_templatenfrom flask_uploads import UploadSet, configure_uploads, IMAGES, patch_request_classnfrom flask_wtf import FlaskFormnfrom flask_wtf.file import FileField, FileRequired, FileAllowednfrom wtforms import SubmitFieldnnapp = Flask(__name__)napp.config[SECRET_KEY] = I have a dreamnapp.config[UPLOADED_PHOTOS_DEST] = os.getcwd()nnphotos = UploadSet(photos, IMAGES)nconfigure_uploads(app, photos)npatch_request_class(app) # set maximum file size, default is 16MBnnnclass UploadForm(FlaskForm):n photo = FileField(validators=[n FileAllowed(photos, u只能上傳圖片!), n FileRequired(u文件未選擇!)])n submit = SubmitField(u上傳)nnn@app.route(/, methods=[GET, POST])ndef upload_file():n form = UploadForm()n if form.validate_on_submit():n filename = photos.save(form.photo.data)n file_url = photos.url(filename)n else:n file_url = Nonen return render_template(index.html, form=form, file_url=file_url)nnnif __name__ == __main__:n app.run()n
模板文件:index.html
<!DOCTYPE html>n<title>Upload File</title>n<h1>圖片上傳</h1>n<form method="POST" enctype="multipart/form-data">n {{ form.hidden_tag() }}n {{ form.photo }}n {% for error in form.photo.errors %}n <span stylex="color: red;">{{ error }}</span>n {% endfor %}n {{ form.submit }}n</form>nn{% if file_url %}n<br><img src="{{ file_url }}">n{% endif %}n
Gist地址:https://gist.github.com/greyli/81d7e5ae6c9baf7f6cdfbf64e8a7c037
文件在資料庫的表示
肯定有人想把文件存到資料庫里,胡亂試了一通後發現沒法子。甚至還有人想要把文件轉換成base64編碼存起來。這不是一心想把資料庫玩壞么……資料庫不是用來存文件的,文件應該放到硬碟里。資料庫里只存儲文件名。
存儲文件名,然後使用的時候在視圖函數里通過Flask-Uploads提供的url()方法獲取URL,或是用Flask提供的send_from_directory()方法獲取(參考這個系列第一篇文章)。
更正:出於文件管理的需要,不應該直接存儲URL。
相關鏈接
- Flask-WTF項目地址:https://github.com/lepture/flask-wtf
- Flask-WTF文件上傳:http://flask-wtf.readthedocs.io/en/stable/form.html#module-flask_wtf.file
- Flask-WTF文件上傳欄位及驗證函數:http://flask-wtf.readthedocs.io/en/stable/api.html?highlight=upload#flask_wtf.file.FileField
- Demo Gist地址:https://gist.github.com/greyli/81d7e5ae6c9baf7f6cdfbf64e8a7c037
- - - - -
更多關於Flask和Web開發的原創內容,歡迎關注知乎專欄 - Hello, Flask!。
推薦閱讀: