處理表單數據
- 從獲取數據到保存數據要經過以下步驟:
- 解析請求獲取表單數據
- 對數據進行必要的轉換,例如把勾選框的結果轉換爲布爾值
- 驗證數據是否符合要求,驗證CSRF令牌
- 如果驗證未通過,生成錯誤消息,並在模板中顯示
- 如果通過驗證,把數據存儲到數據庫裏,並做下一步處理。
在較大的項目中手動處理並不現實,使用Flask-WTF 和 WTForms可以極大簡化這些步驟。
提交表單
HTML中當<form>標籤內類型爲submit的提交字段被單擊時就會創建一個提交表單的HTML請求,請求中包含表單中各個字段的數據。表單的提交由以下3個屬性控制:
action 提交表單時發送請求的目標URL
method 提交表單的HTML請求方法,GET或POST
enctype 表單數據的編碼類型
GET方法只適用於長度不超過3000字符,且不包含敏感信息的表單。因爲這種方法會直接將用戶提交的表單數據暴露在URL中。我們一般使用POST方法提交表單。在使用POST方法時,按照默認編碼類型表單數據會被存儲在請求主體中。Flask中默認監聽GET方法,爲了接收POST請求,必須在路由中使用methods關鍵字指定POST方法。
@app.route('/basic',methods=['POST','GET'])
def basic():
form = LoginForm()
return render_template('login.html', form=form)
驗證表單數據
一、客戶端驗證和服務端驗證。
1.客戶端驗證
在客戶端對用戶的輸入進行驗證。使用HTML5中內置的驗證屬性就可以實現基本客戶端驗證。例如:
<input type="text" name="username" placeholder="輸入用戶名" required>
required 驗證輸入是否爲空,如果用戶沒有輸入內容就點擊了提交按鈕,會彈出瀏覽器內置的錯誤提示。
2.服務器驗證
服務器端認證必不可少,因爲用戶可以繞過客戶端認證。我們使用WTForms實現服務器驗證。
二、WTForms驗證機制
WTForms驗證表單字段的方式是在實例化表單類時傳入表單數據,然後對錶單實例調用validate()方法。這會逐個對字段調用字段實例化時定義的驗證器,返回表示驗證結果的布爾值。如果驗證失敗了就會把錯誤消息存儲到表單實例的errors屬性對應的字典中。
三、在視圖函數中驗證表單
現在視圖中同時接受GET和POST兩種請求,所以我們要根據請求方法的不同指向不同代碼。具體來說:首先實例化表單,如果是GET請求,那就渲染模板;如果是POST請求,就調用validate()方法驗證表單數據。
請求的HTTP方法可以通過request.method屬性獲取。
@app.route('/basic',methods=['POST','GET'])
def basic():
form = LoginForm()
if form.validate_on_submit():
pass
return render_template('login.html', form=form)
validate_on_submit()方法等同於
def basic():
form = LoginForm()
if request.method=='POST' and form.validate():
pass #處理POST請求
return render_template('login.html', form=form)
需要注意,如果表單的StringField和PasswordField沒有validators,那麼form.validate_on_submit()就會一直是false。
簡單處理表單,提交併驗證後在basic頁面閃現用戶名:
@app.route('/basic', methods=['POST', 'GET']) def basic(): form = LoginForm() if form.validate_on_submit(): username = form.username.data flash('Welcome home, %s!' % username) return redirect(url_for('index')) return render_template('login.html', form=form)
效果如下:
提交表單後
PRG模式
在瀏覽器種,默認的刷新操作是發送上一個請求。如果上一個請求是POST的話,刷新時就會彈出一個確認窗口,詢問用戶是否確認再次提交表單。爲了避免這樣的問題,我們儘量不要讓提交表單的POST請求作爲最後一個請求。這就是爲什麼在處理表單後返回了redirect重定向,這會讓瀏覽器重新發送一個GET請求到目標URL。最終,最後一個請求變成了GET。這種防止重複提交 表單的方法就是PRG(Post/ Redirect/ Get)模式。