Try   HackMD

Flask實作_ext_15_Flask_Uploads搭配Flask-wtf

tags: flask flask_ext python uploads wtform

Flask實作_ext_14_Flask_Uploads中提到,flask-uploads可以搭配flask-wtf一起使用,讓我們一起來看怎麼結合應用。

範例

承接Flask實作_ext_14_Flask_Uploads範例,我們已經有完成一個簡單的檔案上傳的板,但實作上我們會使用flask-wtf來快速開發表單,這時候可以利用flask-wtfFileFieldFileRequiredFileAllowed來搭配flask-uploads作業,這是flask-wtf早就已經預留好的接口。

我們加追importflask-wtfwtform的部份package,如下:

from flask_wtf import FlaskForm from wtforms import SubmitField from flask_wtf.file import FileField, FileAllowed, FileRequired

然後設置一個很簡單的Form,如下:

class FormUploads(FlaskForm): btn_uploads = FileField('uploads', validators=[ FileAllowed(abc, 'IMAGE ONLY'), FileRequired('IMAGE REQUIRED PLEASE') ]) submit = SubmitField('Upload_IMG')

第2行:設置一個FileField,加入兩個驗證項,一個是必需有照片,一個是只允許照片。
第3行:FileAllowed的第一個參數是UploadSet的物件名稱,我們案例為abc

新增一個View Function(在同一個Python文件上),如下:

@app.route('/upload_wtf/', methods=['GET','POST']) def upload_wtf(): form = FormUploads() if form.validate_on_submit(): file_name = abc.save(form.btn_uploads.data) file_url = abc.url(file_name) print(file_name, file_url) return render_template('abc.html', form=form, file_url=file_url) else: file_url=None return render_template('abc.html', form=form, file_url = file_url)

第5行:利用UploadSet.save來取得form的資料,不再是利用request來取得資料
第6行:利用UploadSet.url來取得路徑
第10行:設置file_url這參數的用意是為了在上傳之後把照片顯示在畫面上,所以初始設置為None

最後再加入一個Html來渲染頁面,如下:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form method="POST" action="{{ url_for('upload_wtf') }}" enctype="multipart/form-data"> <div> {{ form.hidden_tag() }} {{ form.btn_uploads}} {# error message #} {% for error in form.btn_uploads.errors %} <span>{{ error }}</span> {% endfor %} {{ form.submit }} </div> <div> {% if file_url %} <img src="{{ file_url }}" alt=""> {% endif %} </div> </form> </body> </html>

第8行:記得設置enctype="multipart/form-data"
第13行:錯誤訊息設置
第19行:判斷file_url是否有東西,有的話就顯示照片

接下來我們一起來測試一下專案連結http://127.0.0.1:5000/upload_wtf/,如下:

  • 首先測試的是沒有選擇檔案的情況下按下上傳照片

  • 測試檔案上傳錯誤格式

  • 測試上傳正常的照片


如果有多檔上傳需求的話,則是在Html上設置欄位的時候給予屬性{{ form.btn_uploads(multiple="multiple") }}就可以滿足多選功能,下圖是設置與否的Html差異,當然如果設置了多選的話我們的後端這邊也必需調整為迴圈來取值。

結論

透過上面的案例我們看到結合flask_wtf.ext的三個類別可以讓專案快速的整合flask-uploads來完成簡單的檔案上傳應用,進階如拖拉上傳就可以利用HTML5或是JQUERY來達成,這部份就不多說。

最後,要注意到官方文件有提到,如果flask_wtfFileFelid沒有搭配flask-uploads一起使用的話,必需使用from werkzeug.utils import secure_filenameserure_filename來避免資訊安全問題,務必特別注意。

Flask_Uploads:Flask實作_ext_14_Flask_Uploads