Flask-WTF 表單驗證

Pei Cheng
PyLadies Taiwan
Published in
7 min readNov 6, 2017

在建立網站時,常常會碰到需要取得使用者輸入的資料,例如連絡表單、註冊/登入表單、訂閱電子報等。隨著資料越來越多,怎麼有結構的處理資料,並且在將資料送入資料庫之前驗證資料符合需求,成為現在網站開發的重要一環。在《Flask Web 開發實戰》第二次活動介紹了使用 Flask-WTF 套件處理生成和取得表單資料。表單生成後,送進來的資料要怎麼驗證呢?本篇將介紹 Flask-WTF 的表單驗證。

source: Flask-WTF 官網

表單生成

在第二次活動中提到利用 Flask-Bootstrap 來美化表單,生成的表單在現今較新的瀏覽器裡會進行表單驗證,並提供錯誤訊息 (樣式隨瀏覽器不同會改變)。本篇文章為了探索 Flask-WTF 的資料驗證,在 form 元素加上novalidate 屬性來告訴瀏覽器送出表單資料前不要進行驗證。延續第二次活動的投影片,修改此行即可關掉瀏覽器的驗證。

{{wtf.quick_form(form, novalidate=True)}}

想要知道 Flask-Bootstrapwtf.html 裡的其他設定,可參考 Flask-BootstrapWTForms support 文件或在 GitHub 的原始碼

以下範例是接續第二次活動的表單範例,為了簡潔起見,文章中列出 form class 的內容,文章結尾列出完整程式碼,本文範例都是使用 wtf.quick_form 方法產生。

輸入欄位為必填、長度限制以及比較輸入內容

WTF 的官方文件中談到必填的驗證有分 DataRequired (原本的 Required)和下面程式碼所使用的 InputRequired ,其中 DataRequired 是針對資料做驗證,InputRequired則是單純根據是否有輸入做驗證,官方建議針對欄位是否必填使用 InputRequired 以避免混淆。

長度則使用 Length 驗證,可輸入 minmax 來代表最長和最短的值。

如果需要做兩個欄位輸入值是否相同可以使用 EqualTo 填入所需比較欄位和錯誤訊息即可。

需注意這裡定義的驗證僅限於資料的驗證,在生成表單 HTML 時不會因為設定 length 驗證的 mixmax 值而產生 minlengthmaxlength 屬性。

輸入欄位為 數字、email 或url 等的驗證

這裡定義了三種欄位,首先為 email 欄位,先驗證是否填寫 (InputRequired),再驗證輸入格式是否為 emailemail 僅代表格式符合。實務上仍須其他方式 (如寄送確認信) 確認 email 背後有真的使用者。

url 欄位不是必填,則需加入 Optional 告知 validator 如果沒有填入資料,則不需驗證,填有資料才需要 URL 驗證。這裡如果不填入 Optional ,送出表單時會出現不是正確格式資料的錯誤。

age 欄位的驗證可看出 InputRequiredDataRequired 的不同。IntegerField 是符合整數的值才會有值,如果輸入浮點數如 11.1 會沒有回傳值。利用 InputRequired 可以確認使用者有輸入,DataRequired 則是在輸入後驗證是否符合格式,當收不到值時顯示錯誤訊息。利用傳入的客製化訊息,讓使用者可以清楚理解應該輸入何種類型的資料。

hour 欄位示範 WTForms 提供範圍計算驗證 NumberRange。提供最大值與最小值設定,並且能根據最大和最小值來產生錯誤訊息,之後如果有修改,只需要修改數字,不需要修改訊息即可自動更新訊息裡所顯示數字。

IntegerField 在 HTML 是形成 type=text 的輸入框,如果想要 type=number 輸入框,需自行客製表單。在 HTML5 裡針對 emailurl 可以使用type=emailtype=url 的輸入框,並且瀏覽器對其有一定的驗證,目前 WTForms 3 文件裡並沒有看到相關的欄位,如有需要可自行客製表單模板並搭配上述驗證。

WTForms 還提供 IPAddress (包括 IPV4 和 IPV6)、MacAddressUUID 驗證,有需要可參考文件

以正則式 (Regular Expression) 驗證

有時輸入內容需要符合固定格式,Regex 就成為首選。例如想要驗證台灣手機號碼是 09 開頭,後面接 8 個 0-9 的數字,可以使用 ^[0][9][0-9]{8}$ 的正則式做驗證。

如同前面的 email 驗證,手機號碼的驗證實務上需要其它方式 (如簡訊驗證碼等) 證明手機號碼為真實使用者所持有。

時間與選單

在 WTForms 裡,提供日期 (DateField) 和日期時間 (DateTimeField) 輸入框,所生成的 HTML 是以 type=text 輸入框搭配資料格式驗證,除非輸入的資料符合格式,不然無法通過驗證。如果需要日期選單,需要使用其他套件(WTForms 文件介紹使用 dateutil extension)。或者使用 HTML5 的 type=date 輸入框在較新的瀏覽器也會產生日期下拉選單。

下拉選單是生成基本的 HTML 下拉選單,關於選擇另外還有 RadioField, SelectMultipleField 等輸入方式可以選擇。

Google reCAPTCHA 驗證

Source: Google reCAPTCHA Guide

Google reCAPTCHA「我不是機器人」驗證發展到現在有 V1, V2, Invisible 三個本版,其中 V1 即將退休,Invisible 是今年推出的新版。當網頁上使用 V2 版本時,需要使用者勾選「我不是機器人」選項(如上圖所示),當判斷使用者可能是機器人時,會跳出題目要使用者判斷。Invisble 則是不需要一開始勾選,只有在判斷使用者可能是機器人時才會跳出要求使用者選取的題目,減少打斷使用者操作的可能性。WTForms 目前提供 V2 版本可以快速套用。使用 Google reCAPTCHA 需要先申請 Site Key Secret Key 並在申請時填入網域才能執行。如果是測試或練習,可以使用 FAQ 文件 所提供的 test key 跳過申請步驟。以下範例是使用 test key。 設定 key 值時,WTForms 文件裡的 RECAPTCHA_PUBLIC_KEY 對應 Google reCAPTCHASite KeyRECAPTCHA_PRIVATE_KEYSecret Key

使用 test key 時,每次勾選都會通過驗證,應用在專案上應透過 reCAPTCHA Admin Panel 申請專屬 key 值。

將上面的範例結合起來的範例程式碼如下所示,其中在 index.html 的模板裡在送出表單驗證成功後將資料印在頁面表示有收到輸入值。以本文介紹 Flask-WTF 一系列的表單輸入和驗證方式為起點,更多表單的呈現和驗證方式正等著你去探索。

參考資料

--

--