# Flask實作_ext_15_Flask_Uploads搭配Flask-wtf ###### tags: `flask` `flask_ext` `python` `uploads` `wtform` :::danger 前置閱讀: * [Flask實作_ext_14_Flask_Uploads](https://hackmd.io/s/BJPLnPHJX) ::: 在[Flask實作_ext_14_Flask_Uploads](https://hackmd.io/s/BJPLnPHJX)中提到,`flask-uploads`可以搭配`flask-wtf`一起使用,讓我們一起來看怎麼結合應用。 ## 範例 承接[Flask實作_ext_14_Flask_Uploads](https://hackmd.io/s/BJPLnPHJX)範例,我們已經有完成一個簡單的檔案上傳的板,但實作上我們會使用`flask-wtf`來快速開發表單,這時候可以利用`flask-wtf`的`FileField`、`FileRequired`、`FileAllowed`來搭配`flask-uploads`作業,這是`flask-wtf`早就已經預留好的接口。 我們加追import`flask-wtf`與`wtform`的部份package,如下: ```python= from flask_wtf import FlaskForm from wtforms import SubmitField from flask_wtf.file import FileField, FileAllowed, FileRequired ``` 然後設置一個很簡單的Form,如下: ```python= 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<sub>(在同一個Python文件上)</sub>,如下: ```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來渲染頁面,如下: ```htmlmixed= <!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/`,如下: * 首先測試的是沒有選擇檔案的情況下按下上傳照片 ![](https://i.imgur.com/EHPmrEN.png) * 測試檔案上傳錯誤格式 ![](https://i.imgur.com/KRRp12Q.png) * 測試上傳正常的照片 ![](https://i.imgur.com/o9RwCQq.png) ![](https://i.imgur.com/v6I55dk.png) 如果有多檔上傳需求的話,則是在Html上設置欄位的時候給予屬性`{{ form.btn_uploads(multiple="multiple") }}`就可以滿足多選功能,下圖是設置與否的Html差異,當然如果設置了多選的話我們的後端這邊也必需調整為迴圈來取值。 ![](https://i.imgur.com/hd9HhKa.png) ## 結論 透過上面的案例我們看到結合`flask_wtf.ext`的三個類別可以讓專案快速的整合`flask-uploads`來完成簡單的檔案上傳應用,進階如拖拉上傳就可以利用HTML5或是JQUERY來達成,這部份就不多說。 最後,要注意到官方文件有提到,如果`flask_wtf`的`FileFelid`沒有搭配`flask-uploads`一起使用的話,必需使用`from werkzeug.utils import secure_filename`的`serure_filename`來避免資訊安全問題,務必特別注意。 **Flask_Uploads:**[Flask實作_ext_14_Flask_Uploads](https://hackmd.io/s/BJPLnPHJX)