Flask Web第四章
第四章
4.2使用Flask—WTF處理表單
-
預設為每個表單啟用CSRF保護,為我們自動生成和驗證CSRF令牌
-
預設使用程式祕鑰對CSRF令牌簽名,設定祕鑰:app.secret_key = os.getenv('SECRET_KEY', 'secret string')
4.2.1定義表單類
-
使用WTForms建立表單時,類要繼承從WTForms匯入的Form基類
-
欄位屬性通過例項化WTForms提供的欄位類表示,名稱作為對應HTML<input>元素的name屬性和id屬性。注意:名稱大小寫敏感,不能以下劃線或validate開頭
-
例項化欄位類的引數有:
-
label:欄位標籤<label>的值,也就是渲染後再輸入欄位前的提示文字
-
render_kw:字典型別,設定<input>標籤的屬性,如{‘'placeholder':'haha'}
-
validators:列表,包含一系列驗證器。驗證器是用於驗證欄位資料的類,從wtforms.validators模組匯入。例項化驗證類時,message引數傳入自定義錯誤資訊
-
default:字串或可呼叫物件,給欄位設定預設值
-
-
-
使用Flask—WTF建立表單,要繼承FlaskForm類,其他操作與上條一樣
4.2.2輸出HTML程式碼
-
輸出欄位的HTML程式碼,用’form.欄位名‘。如:form.username
-
輸出欄位<label>的代買,用"form.欄位名.label".如:form.username.label
-
給欄位增加屬性
-
使用render_kw屬性
-
在呼叫時加括號使用關鍵字引數的形式傳入。如:form.username(style='width:20px;',class='bar')
-
4.2.3模板渲染表單
-
呼叫表單類的欄位屬性即可,同時也可以新增括號增加欄位屬性
{{form.username}} / {{form.username(class='bar')}}
-
Flask-WTF自動驗證CSRF令牌,所以為了通過驗證,需手動渲染這個欄位。{{form.csrf_token}}
4.3.2驗證表單資料
-
單純使用WTForms,例項化表單類時要把request.form出入表單類,而Flask-WTF,不需要手動傳入。注意:POST提交的表單,通過request.form獲取資料,而GET提交的表單,通過request.args獲取資料
-
驗證表單
-
首先例項化表單,再呼叫validate()方法驗證表單。若對GET和POST請求執行不同程式碼,如GET渲染模板,POST呼叫validate()方法驗證資料。即if reques.method =='POST' and form.validate():
-
form.validate_on_submit()合併了上面兩個操作,但除了POST方法,PUT、PATCH、DELETE也會驗證表單資料
-
form.data是匹配所有欄位與對應資料的字典,一般使用form.欄位屬性名.data獲取對應欄位的資料列表
-
對錶單的請求使用PRG(Post/Redirect/Get)模式,即:對請求表單的POST請求返回重定向響應將最後一個請求轉換為GET請求
-
4.3.3模板渲染錯誤訊息
-
form.errors匹配所有欄位與對應錯誤訊息的字典,一般使用form.欄位屬性名.errors獲取對應欄位的錯誤訊息列表
-
像渲染flash()訊息一樣,可以使用for迴圈迭代錯誤訊息列表
-
疑問:驗證失敗將錯誤訊息新增到表單類例項的errors屬性是自動進行的嗎?不需手動傳遞?
4.4.2使用巨集渲染表單
-
模板渲染需要重複做的工作:
-
呼叫欄位屬性,獲取<input>定義
-
呼叫對應的label屬性,獲取<label>定義
-
渲染錯誤訊息
-
-
macro.html的內容:
{% macro form_field(field) %}
{{ field.label }}<br>
{{ field(**kwargs) }}<br>
{% if field.errors %}
{% for error in field.errors%}
...
{% endfor%}
{% endif %}
{% endmacro %}
-
模板檔案渲染的內容:
{% from 'macro.html' import form_field %}
<form method='POST'>
{{ form.csrf_token }}
{{ form_field(form.username) }}
form>
4.4.3自定義驗證器
-
行內驗證器
-
在表單類中定義以“validate_欄位屬性名”形式命名的方法,該方法接收兩個位置引數,依次是form和field,前者是表單例項,後者是欄位物件,field.data獲取欄位資料,這兩個位置引數在驗證表單時被呼叫傳入。驗證出錯丟擲ValidationError異常,傳入錯誤資訊做引數,如raise ValidationError('錯了資訊')
-
-
全域性驗證器
-
實現工廠函式,即返回一個可呼叫的函式
-
4.4.4檔案上傳
-
app.config['MAX_CONTENT_LENGTH']=1024*3 注意:預設單位為位元組。app.config['UPLOAD_PATH']配置上傳檔案的目的資料夾
-
檔案上傳表單,需將表單的enctype屬性設為“multipart/form-data”
-
手動處理時,request.files.get('photo')獲取。當使用Flask—WTF時,會自動幫我們獲取對應的檔案物件,仍使用表單類屬性的data屬性獲取,如:form.欄位名.data
-
使用檔案物件的save(‘檔案儲存路徑'')方法儲存檔案。如:
f=form.photo.data
f.save('/uploads/photo.jpg')
-
send_from_directory(),通過傳入的檔案路徑返回相應的檔案內容,類似Flask內建的static檢視
-
多檔案上傳時,使用request.files。getlist('photo')獲取所有上傳檔案物件的列表
4.4.6單表單多提交按鈕
-
只有被單擊的提交欄位才會解析到request.form字典中。一般使用form.欄位名.data,被單擊的值是True,未被單擊則是False
4.4.7單頁面多表單
-
單檢視處理
-
一個頁面多個表單時,要判斷是哪個表單被提交。Flask-WTF根據請求方法判斷表單是否提交,不判斷是哪個表單被提交,需要手動判斷。
-
可以給兩個表單的提交欄位設定不同的name屬性,使用form.欄位名.data判斷是否被提交
-
-
多檢視處理
-
使用不同檢視函式對錶單進行處理,兩表單的提交欄位的name可以使用相同名稱,在檢視函式中可繼續form.validate_on_submit()方法驗證
-
疑問:
-