flask 處理表單數據 --


處理表單數據

表單數據的處理涉及很多內容,從獲取數據到保存數據大致有以下步驟:

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

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

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

4、  如果驗證未通過則需要生成錯誤消息,並在模板中顯示錯誤消息。

5、  如果驗證通過,就把數據保存到數據庫或做進一步處理

使用Flask-WTF和WTForms可以極大地簡化這些步驟

 

提交表單

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

 

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

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

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)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM