1. 程式人生 > 其它 >Flask Web第四章

Flask Web第四章

第四章

4.2使用Flask—WTF處理表單

  1. 預設為每個表單啟用CSRF保護,為我們自動生成和驗證CSRF令牌

  2. 預設使用程式祕鑰對CSRF令牌簽名,設定祕鑰:app.secret_key = os.getenv('SECRET_KEY', 'secret string')

4.2.1定義表單類

  1. 使用WTForms建立表單時,類要繼承從WTForms匯入的Form基類

    • 欄位屬性通過例項化WTForms提供的欄位類表示,名稱作為對應HTML<input>元素的name屬性和id屬性。注意:名稱大小寫敏感,不能以下劃線或validate開頭

    • 例項化欄位類的引數有:

      • label:欄位標籤<label>的值,也就是渲染後再輸入欄位前的提示文字

      • render_kw:字典型別,設定<input>標籤的屬性,如{‘'placeholder':'haha'}

      • validators:列表,包含一系列驗證器。驗證器是用於驗證欄位資料的類,從wtforms.validators模組匯入。例項化驗證類時,message引數傳入自定義錯誤資訊

      • default:字串或可呼叫物件,給欄位設定預設值

  2. 使用Flask—WTF建立表單,要繼承FlaskForm類,其他操作與上條一樣

4.2.2輸出HTML程式碼

  1. 輸出欄位的HTML程式碼,用’form.欄位名‘。如:form.username

  2. 輸出欄位<label>的代買,用"form.欄位名.label".如:form.username.label

  3. 給欄位增加屬性

    • 使用render_kw屬性

    • 在呼叫時加括號使用關鍵字引數的形式傳入。如:form.username(style='width:20px;',class='bar')

4.2.3模板渲染表單

  1. 呼叫表單類的欄位屬性即可,同時也可以新增括號增加欄位屬性

    {{form.username}} / {{form.username(class='bar')}}

  2. Flask-WTF自動驗證CSRF令牌,所以為了通過驗證,需手動渲染這個欄位。{{form.csrf_token}}

4.3.2驗證表單資料

  1. 單純使用WTForms,例項化表單類時要把request.form出入表單類,而Flask-WTF,不需要手動傳入。注意:POST提交的表單,通過request.form獲取資料,而GET提交的表單,通過request.args獲取資料

  2. 驗證表單

    • 首先例項化表單,再呼叫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模板渲染錯誤訊息

  1. form.errors匹配所有欄位與對應錯誤訊息的字典,一般使用form.欄位屬性名.errors獲取對應欄位的錯誤訊息列表

  2. 像渲染flash()訊息一樣,可以使用for迴圈迭代錯誤訊息列表

  3. 疑問:驗證失敗將錯誤訊息新增到表單類例項的errors屬性是自動進行的嗎?不需手動傳遞?

4.4.2使用巨集渲染表單

  1. 模板渲染需要重複做的工作:

    • 呼叫欄位屬性,獲取<input>定義

    • 呼叫對應的label屬性,獲取<label>定義

    • 渲染錯誤訊息

  1. macro.html的內容:

    {% macro form_field(field) %}
    {{ field.label }}<br>
    {{ field(**kwargs) }}<br>
    {% if field.errors %}
    {% for error in field.errors%}
    ...
    {% endfor%}
    {% endif %}
    {% endmacro %}
  1. 模板檔案渲染的內容:

    {% from 'macro.html' import form_field %}

    <form method='POST'>
    {{ form.csrf_token }}
    {{ form_field(form.username) }}
    form>

4.4.3自定義驗證器

  1. 行內驗證器

    • 在表單類中定義以“validate_欄位屬性名”形式命名的方法,該方法接收兩個位置引數,依次是form和field,前者是表單例項,後者是欄位物件,field.data獲取欄位資料,這兩個位置引數在驗證表單時被呼叫傳入。驗證出錯丟擲ValidationError異常,傳入錯誤資訊做引數,如raise ValidationError('錯了資訊')

  1. 全域性驗證器

    • 實現工廠函式,即返回一個可呼叫的函式

4.4.4檔案上傳

  1. app.config['MAX_CONTENT_LENGTH']=1024*3 注意:預設單位為位元組。app.config['UPLOAD_PATH']配置上傳檔案的目的資料夾

  2. 檔案上傳表單,需將表單的enctype屬性設為“multipart/form-data”

  3. 手動處理時,request.files.get('photo')獲取。當使用Flask—WTF時,會自動幫我們獲取對應的檔案物件,仍使用表單類屬性的data屬性獲取,如:form.欄位名.data

  4. 使用檔案物件的save(‘檔案儲存路徑'')方法儲存檔案。如:

    f=form.photo.data

    f.save('/uploads/photo.jpg')

  1. send_from_directory(),通過傳入的檔案路徑返回相應的檔案內容,類似Flask內建的static檢視

  2. 多檔案上傳時,使用request.files。getlist('photo')獲取所有上傳檔案物件的列表

4.4.6單表單多提交按鈕

  1. 只有被單擊的提交欄位才會解析到request.form字典中。一般使用form.欄位名.data,被單擊的值是True,未被單擊則是False

4.4.7單頁面多表單

  1. 單檢視處理

    • 一個頁面多個表單時,要判斷是哪個表單被提交。Flask-WTF根據請求方法判斷表單是否提交,不判斷是哪個表單被提交,需要手動判斷。

    • 可以給兩個表單的提交欄位設定不同的name屬性,使用form.欄位名.data判斷是否被提交

  2. 多檢視處理

    • 使用不同檢視函式對錶單進行處理,兩表單的提交欄位的name可以使用相同名稱,在檢視函式中可繼續form.validate_on_submit()方法驗證

    • 疑問: