Flask-WTF 表單驗證
在建立網站時,常常會碰到需要取得使用者輸入的資料,例如連絡表單、註冊/登入表單、訂閱電子報等。隨著資料越來越多,怎麼有結構的處理資料,並且在將資料送入資料庫之前驗證資料符合需求,成為現在網站開發的重要一環。在《Flask Web 開發實戰》第二次活動介紹了使用 Flask-WTF 套件處理生成和取得表單資料。表單生成後,送進來的資料要怎麼驗證呢?本篇將介紹 Flask-WTF 的表單驗證。
表單生成
在第二次活動中提到利用 Flask-Bootstrap 來美化表單,生成的表單在現今較新的瀏覽器裡會進行表單驗證,並提供錯誤訊息 (樣式隨瀏覽器不同會改變)。本篇文章為了探索 Flask-WTF 的資料驗證,在 form
元素加上novalidate
屬性來告訴瀏覽器送出表單資料前不要進行驗證。延續第二次活動的投影片,修改此行即可關掉瀏覽器的驗證。
{{wtf.quick_form(form, novalidate=True)}}
想要知道 Flask-Bootstrap 的 wtf.html 裡的其他設定,可參考 Flask-Bootstrap的 WTForms support 文件或在 GitHub 的原始碼。
以下範例是接續第二次活動的表單範例,為了簡潔起見,文章中列出 form class
的內容,文章結尾列出完整程式碼,本文範例都是使用 wtf.quick_form
方法產生。
輸入欄位為必填、長度限制以及比較輸入內容
在 WTF 的官方文件中談到必填的驗證有分 DataRequired
(原本的 Required
)和下面程式碼所使用的 InputRequired
,其中 DataRequired
是針對資料做驗證,InputRequired
則是單純根據是否有輸入做驗證,官方建議針對欄位是否必填使用 InputRequired
以避免混淆。
長度則使用 Length
驗證,可輸入 min
和 max
來代表最長和最短的值。
如果需要做兩個欄位輸入值是否相同可以使用 EqualTo
填入所需比較欄位和錯誤訊息即可。
需注意這裡定義的驗證僅限於資料的驗證,在生成表單 HTML 時不會因為設定 length
驗證的 mix
和 max
值而產生 minlength
和 maxlength
屬性。
輸入欄位為 數字、email 或url 等的驗證
這裡定義了三種欄位,首先為 email
欄位,先驗證是否填寫 (InputRequired
),再驗證輸入格式是否為 email
。email
僅代表格式符合。實務上仍須其他方式 (如寄送確認信) 確認 email 背後有真的使用者。
url
欄位不是必填,則需加入 Optional
告知 validator 如果沒有填入資料,則不需驗證,填有資料才需要 URL
驗證。這裡如果不填入 Optional
,送出表單時會出現不是正確格式資料的錯誤。
age
欄位的驗證可看出 InputRequired
和 DataRequired
的不同。IntegerField
是符合整數的值才會有值,如果輸入浮點數如 11.1 會沒有回傳值。利用 InputRequired
可以確認使用者有輸入,DataRequired
則是在輸入後驗證是否符合格式,當收不到值時顯示錯誤訊息。利用傳入的客製化訊息,讓使用者可以清楚理解應該輸入何種類型的資料。
hour
欄位示範 WTForms
提供範圍計算驗證 NumberRange
。提供最大值與最小值設定,並且能根據最大和最小值來產生錯誤訊息,之後如果有修改,只需要修改數字,不需要修改訊息即可自動更新訊息裡所顯示數字。
IntegerField
在 HTML 是形成 type=text
的輸入框,如果想要 type=number
輸入框,需自行客製表單。在 HTML5 裡針對 email
和 url
可以使用type=email
和 type=url
的輸入框,並且瀏覽器對其有一定的驗證,目前 WTForms
3 文件裡並沒有看到相關的欄位,如有需要可自行客製表單模板並搭配上述驗證。
WTForms
還提供 IPAddress
(包括 IPV4 和 IPV6)、MacAddress
和 UUID
驗證,有需要可參考文件。
以正則式 (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 驗證
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 reCAPTCHA 的 Site Key
,RECAPTCHA_PRIVATE_KEY
為 Secret Key
。
使用 test key 時,每次勾選都會通過驗證,應用在專案上應透過 reCAPTCHA Admin Panel 申請專屬 key 值。
將上面的範例結合起來的範例程式碼如下所示,其中在 index.html 的模板裡在送出表單驗證成功後將資料印在頁面表示有收到輸入值。以本文介紹 Flask-WTF 一系列的表單輸入和驗證方式為起點,更多表單的呈現和驗證方式正等著你去探索。
參考資料
- PyLadies Taiwan: Facebook 粉絲頁、Meetup
- Flask 官網:Welcome | Flask (A Python Microframework)
- Flask-WTF 官網: https://flask-wtf.readthedocs.io/
- WTForms 文件:Fields, Validators
- Flask Web 開發實戰 — 02: 投影片