flask 處理表單數據 --

處理表單數據

表單數據的處理涉及不少內容,從獲取數據到保存數據大體有如下步驟:html

一、  解析請求,獲取表單數據java

二、  對數據進行必要的轉換,好比講勾選框的值轉換成python的布爾值python

三、  驗證數據是否符合要求,同時驗證CSRF令牌。web

四、  若是驗證未經過則須要生成錯誤消息,並在模板中顯示錯誤消息。數據庫

五、  若是驗證經過,就把數據保存到數據庫或作進一步處理flask

使用Flask-WTF和WTForms能夠極大地簡化這些步驟瀏覽器

 

提交表單

在HTML中,當<form>標籤聲明的表單中類型爲submit的提交字段被單擊時,就會建立一個表單的HTTP請求,請求中包含表單各個字段的數據。表單的提交行爲主要有三個屬性控制,以下表:安全

 

form標籤的action屬性用來指定表單被提交的目標URL,默認爲當前URL,就是渲染該模板的路由所在的URL。服務器

當使用get方法提交表單時,表單的數據會以查詢字符串的形式附加在請求的URL裏,如:app

127.0.0.1:5000:/basic?username=xiaxiaoxu&password=12345

GET方式僅適用於長度不超過3000個字符,且不包含敏感信息的表單。由於這種方式會直接將用戶提交的表單數據暴露在URL中,容易被攻擊者截獲,實例中的狀況是危險的。所以到處於安全的考慮,咱們通常使用post方法提交表單。使用post方式時,按照默認的編碼類型,表單數據會存儲在請求主體中,好比:

POST /basic HTTP/1.0

Content-Type:application/x-www-form-urlencoded

Content-Length:30

 

username=xiaxiaoxu&12345

 

Flask爲路由設置默認的監聽方法是GET,爲了支持接收表單提交發送的POST請求,咱們須要在app.route()裝飾器裏使用methods關鍵字爲路由指定HTTP方法,好比:

@app.route('/',methods=['GET','POST'])
def basic():
    form=LoginForm()
    return render_template('basic.html',form=form)

 

驗證表單數據

客戶端驗證和服務器端驗證

表單的驗證一般分爲如下幾種形式

客戶端驗證

客戶端驗證是指在客戶端(好比web瀏覽器)對用戶的輸入值進行驗證。好比,使用HTML5內置的驗證屬性便可實現基本的客戶端驗證(type、required、min、max、accept等)。

例如,給username字段添加required標誌:

<input type=」text」 name=」username」 required>

若是用戶沒有輸入內容而按下提交按鈕,會彈出瀏覽器內置的錯誤提示

 

和其餘附件HTML屬性相同,咱們能夠在定義表單時經過render_kw傳入這些屬性,或是在渲染表單時傳入,像requiredd這類布爾值屬性,值能夠爲空或是任意ASCII字符,如:

{{ form.username(required=’’) }}

 

除了使用HTML5提供的屬性實現基本的客戶端驗證,咱們一般會使用javaScript實現完善的驗證機制,好比使用javaScript表單驗證庫-jQuery

 

客戶端方式能夠實時動態提示用戶輸入是否正確,只有用戶輸入正確後纔會將表單數據發送到服務器,客戶端驗證能夠加強用戶體驗,下降服務器負載。

 

服務器端驗證

 

服務器端驗證是指用戶把輸入的數據提交到服務器端,在服務器端對數據進行驗證。若是驗證出錯就會在響應中加入錯誤信息。用戶修改後再提交表單,知道經過驗證。在flask中使用WTForms實現的就是服務器端驗證

 

 

WTForms驗證機制

WTForms驗證表單字段的方式是在實例化表單類時傳入表單數據,而後對錶單實例調用validate()方法。這會逐個對字段調用字段實例化時定義的驗證器,返回表示驗證結果的布爾值。若是驗證失敗,就把錯誤消息存儲到表單實例的errors屬性對應的字典中,驗證的過程以下所示:

 

>>> from app import app
>>> from flask import request
>>> app.test_request_context('/basic').push()#激活請求上下文
>>> from flask import current_app
>>> app.app_context().push()#激活程序上下文
>>> current_app.name
'app'
>>>#定義LoginForm類
>>> from wtforms import Form, StringField,PasswordField,BooleanField
>>> from wtforms.validators import DataRequired,length
>>> class LoginForm(Form):
...     username = StringField('Username', validators=[DataRequired()])
...     password = PasswordField('Password',validators=[DataRequired(),length(8,128)])
...
>>> form = LoginForm(username='',password='123')
>>> form.data  #表單數據字典
{'username': '', 'password': '123'}
>>> form.validate()
False
>>> form.errors
{'username': [u'This field is required.'], 'password': [u'Field must be between 8 and 128 characters long.']}
>>> form2 = LoginForm(username='xiaxiaoxu', password='123456')
>>> form2.data  #表單數據字典
{'username': 'xiaxiaoxu', 'password': '123456'}
>>> form2.validate()
False
>>> form2.errors  #錯誤消息字典
{'password': [u'Field must be between 8 and 128 characters long.']}
>>> form3 = LoginForm(username='xiaxiaoxu', password='123456789')
>>> form3.data
{'username': 'xiaxiaoxu', 'password': '123456789'}
>>> form3.validate()
True
>>> form3.errors
{}

 

由於表單使用POST方法提交,若是單純使用WTForms,在實例化表單時須要首先把request.form傳入表單類(LoginForm(username='',password='123')),而使用Flask-WTF時,表單類繼承的FlaskForm基類默認會從request.form獲取表單數據,因此不須要手動傳入。

 

使用POST方法提交的表單,其數據會被Flask解析成爲一個字典,能夠經過請求對象的form屬性獲取(request.form);使用GET方法提交的表單的數據一樣會被解析爲字典,不過要經過請求對象的args屬性獲取(request.args)。

相關文章
相關標籤/搜索