Flask表單與表單驗(yàn)證實(shí)現(xiàn)流程介紹
表單介紹
說(shuō)到表單,在HTML中表單的創(chuàng)建時(shí)通過(guò)<form>
標(biāo)簽實(shí)現(xiàn)的,在<form>
標(biāo)簽內(nèi)部,字段通過(guò)使用<input>
標(biāo)簽等定義。比如一個(gè)表單內(nèi)部有用戶名,密碼框這些,都是通過(guò)<input>
,<label>
標(biāo)簽等實(shí)現(xiàn)的。
一個(gè)簡(jiǎn)單的表單:
<form> First name:<br> <input type="text" name="firstname"> <br> Last name:<br> <input type="text" name="lastname"> </form>
將表單提交給服務(wù)端處理時(shí),服務(wù)端需要驗(yàn)證表單中的字段的取值是否符合要求。
在 Python 的 Web 開發(fā)中,表單內(nèi)部的字段標(biāo)簽之類的,就不再使用HTML標(biāo)簽來(lái)寫了,而是通過(guò)python類實(shí)現(xiàn)。
WTForms
在python中使用類定義表單,然后直接通過(guò)類定義生成對(duì)應(yīng)的HTML代碼,這種方式更加方便,而且使表單更易于重用。除非是非常簡(jiǎn)單的程序,或者想讓表單的定義更加靈活,否則一般不會(huì)在模板中直接使用HTML代碼寫表單。
WTForms 和 Flask-WTF
WTForms 是一個(gè)靈活的表單驗(yàn)證和表單渲染的庫(kù),它的主要功能:
- 驗(yàn)證表單中的字段的取值是否符合要求;
- 渲染輸出表單的 HTML 代碼
WTForms 可以與任意的 Web 框架和模板引擎一起使用。 在 Flask 框架或者 Django 框架中,都可以使用 WTForms。
Flask-WTF
在 WTForms 的基礎(chǔ)上提供了一些擴(kuò)展,可以方便的在 Flask 框架中生成表單。
創(chuàng)建表單
下面直接用代碼講解如何創(chuàng)建表單。
首先,我們的目標(biāo)是這樣一個(gè)頁(yè)面
一個(gè)簡(jiǎn)單的登錄頁(yè)面,讓用戶輸入用戶名,密碼,同時(shí)對(duì)用戶名和密碼進(jìn)行驗(yàn)證,驗(yàn)證成功就輸出,驗(yàn)證不成功需要重新輸入,并提示錯(cuò)誤信息。
首先,這是一個(gè)表單,表單內(nèi)有一些文本,有文本框,有登錄按鈕,這些都是通過(guò)python中的表單類創(chuàng)建的,使用的正是flask-wtf模塊創(chuàng)建的。
先導(dǎo)入需要的模塊
#導(dǎo)入表單類 from flask_wtf import FlaskForm #導(dǎo)入字段類 from wtforms import StringField,SubmitField,PasswordField #導(dǎo)入驗(yàn)證器類 from wtforms.validators import DataRequired,Length,Regexp
class LoginForm(FlaskForm): ''' 這些字段對(duì)象會(huì)被渲染為html標(biāo)簽 實(shí)例化一個(gè)文本字段對(duì)象,設(shè)置參數(shù) label:這個(gè)值可以拿出來(lái)放在標(biāo)簽前面顯示 validators=[]驗(yàn)證器列表,實(shí)例化的驗(yàn)證器對(duì)象,里面又可以設(shè)置參數(shù) ''' #用戶名字段 username = StringField( label='用戶名', validators=[ DataRequired(message='用戶名不能為空'), Length(3,20,message='用戶名長(zhǎng)度在3-20個(gè)字符') ] ) password = PasswordField( label='密碼', validators=[ DataRequired(message='密碼不能為空'), Length(3,20,message='密碼長(zhǎng)度在3-20個(gè)字符'), Regexp(r'^[a-z0-9A-Z]+$',message='密碼只能有字母,數(shù)字,下劃線組成') ] ) submit = SubmitField(label='登錄')
我們創(chuàng)建了一個(gè)類LoginForm
,它是一個(gè)表單類,繼承了FlaskForm
,這個(gè)表單中包含一個(gè)用戶名username字段,密碼password字段,還有一個(gè)提交按鈕submit,這三個(gè)字段作為了類LoginForm
的三個(gè)屬性。
表單字段
我們發(fā)現(xiàn)用戶名,密碼這些實(shí)際是文本框,既然不用HTML代碼實(shí)現(xiàn),那么怎么實(shí)現(xiàn)呢?
使用的就是WTForms中的各種字段類,比如這里:
username = StringField()
StringField()
是WTForms 支持表單字段類,它表示文本字段,這樣一個(gè)字段會(huì)被渲染為
<input id="username" name="username" type="text" value="">
注意:實(shí)例化對(duì)象的名稱是username ,被渲染后的input標(biāo)簽中的id
和name
屬性值都叫username
WTForms 支持如下類型的表單字段:
這只是一部分,還有很多其他支持的字段。
接著看代碼:
username = StringField( label='用戶名', validators=[ DataRequired(message='用戶名不能為空'), Length(3,20,message='用戶名長(zhǎng)度在3-20個(gè)字符') ] )
驗(yàn)證器
StringField類需要傳遞一些參數(shù):
label='用戶名'
,這個(gè)參數(shù)可以直接在模板頁(yè)面中顯示,使用form.username.label
,把它放在文本框的前面,像下面這樣:
validators=[ ]
這個(gè)參數(shù)表示對(duì)這個(gè)字段使用的驗(yàn)證器列表。驗(yàn)證器就是對(duì)這個(gè)字段使用那些驗(yàn)證,比如這里DataRequired,Length
兩個(gè)驗(yàn)證器類,同樣驗(yàn)證器類需要實(shí)例化然后傳入?yún)?shù)。比如:
Length(3,20,message='用戶名長(zhǎng)度在3-20個(gè)字符')
限定長(zhǎng)度在3-20字符,如果驗(yàn)證不通過(guò),就彈出錯(cuò)誤信息:message='用戶名長(zhǎng)度在6-20個(gè)字符'
。
驗(yàn)證器也有很多類型,常見的驗(yàn)證器類有:
還可以自定義驗(yàn)證器類等等。
我們創(chuàng)建了一個(gè)單獨(dú)的文件loginform.py
from flask_wtf import FlaskForm from wtforms import StringField,PasswordField,SubmitField from wtforms.validators import DataRequired,Regexp,Length class LoginForm(FlaskForm): #<input id="username1" maxlength="20" minlength="3" name="username1" required type="text" value=""> username = StringField( label='用戶名', validators=[ DataRequired(message='用戶名不能為空'), Length(3,20,message='用戶名長(zhǎng)度在3-20個(gè)字符') ] ) password = PasswordField( label='密碼', validators=[ DataRequired(message='密碼不能為空'), Length(3,20,message='密碼長(zhǎng)度在3-20個(gè)字符'), Regexp(r'^[a-z0-9A-Z]+$',message='密碼只能有字母,數(shù)字,下劃線組成') ] ) submit = SubmitField(label='登錄')
表單類創(chuàng)建好之后,可以做一個(gè)簡(jiǎn)單的測(cè)試:
把這個(gè)表單顯示出來(lái)
首先,我們?cè)赼pp.py文件中:
from flask import Flask,render_template,request from loginform import LoginForm app = Flask(__name__) app.config['SECRET_KEY'] = 'hard to guess string' @app.route('/',methods=['GET','POST']) def login(): loginform = LoginForm() if request.method == 'GET': return render_template('login.html',form = loginform) return 'hello' if __name__ == '__main__': app.run()
app.config['SECRET_KEY'] = 'hard to guess string'
用于防范 CSRF 攻擊,具體的我也不清楚,就不再細(xì)說(shuō)了,總之需要設(shè)置
接著,在根路由下/
,有視圖函數(shù)login
,訪問(wèn)這個(gè)路由的方法可以是GET,或者POST。首先假設(shè)是GET,我們就需要把之前的表單渲染出來(lái),具體的做法就是:
使用創(chuàng)建的表單類LoginForm
實(shí)例化一個(gè)表單對(duì)象loginform ,如果請(qǐng)求方法是GET,就去渲染login.html
,然后表單對(duì)象作為參數(shù)傳遞過(guò)去。所以我們還需要設(shè)計(jì)一下login.html
文件。
login.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登錄頁(yè)面</title> </head> <body> <form action="{{ url_for('login') }}" method="post"> <table> <tbody> <tr> <td>{{ form.username.label }}</td> <td>{{ form.username }}</td> <td>{% for err in form.username.errors %} {{ err }} {% endfor %} </td> <td>{{ form.test }}</td> </tr> <tr> <td>{{ form.password.label }}</td> <td>{{ form.password }}</td> <td>{% for err in form.password.errors %} {{ err }} {% endfor %} </td> </tr> <tr> <td>{{ form.submit }}</td> </tr> {{ form.hidden_tag() }} </tbody> </table> </form> </body> </html>
這里使用了一個(gè)表格布局,然后表單的action="{{ url_for('login') }}" method="post"
,設(shè)置了表單的提交路徑,以及提交方法。
<td>{{ form.username.label }}</td>#拿到username的label值顯示出來(lái) <td>{{ form.username }}</td>#顯示username這個(gè)字段 <td>{% for err in form.username.errors %}#這是錯(cuò)誤信息,如果驗(yàn)證不通過(guò)會(huì)顯示錯(cuò)誤信息 {{ err }} {% endfor %} </td>
最后,還要注意到: {{ form.hidden_tag() }}
, 用于防范 CSRF 攻擊,生成 <input id=“csrf_token”/>
標(biāo)簽??傊仨氁由希患由?,后面驗(yàn)證數(shù)據(jù)的時(shí)候會(huì)出問(wèn)題。
接著,運(yùn)行app.py,訪問(wèn)根路徑/
,則是GET方法訪問(wèn),會(huì)渲染出login.htm
l文件。
接著,我們需要實(shí)現(xiàn),用戶輸入數(shù)據(jù),我們進(jìn)行驗(yàn)證,驗(yàn)證不成功就提示錯(cuò)誤信息,驗(yàn)證成功就登錄成功。
回到表單類中,我們可以發(fā)現(xiàn)使用的驗(yàn)證器有這幾種:
其中,DataRequired,Length直接被渲染為HTML中input標(biāo)簽的屬性:
maxlength="" minlength="" required
這時(shí)候驗(yàn)證就是在瀏覽器上完成的了,而不是在服務(wù)器??蛻舳朔绞娇梢詫?shí)時(shí)動(dòng)態(tài)的提示用戶輸入是否正確,只有用戶輸入正確后才會(huì)將表單數(shù)據(jù)發(fā)送給服務(wù)器??蛻舳蓑?yàn)證可以增強(qiáng)用戶體驗(yàn),降低服務(wù)器負(fù)載。
參考書上說(shuō),F(xiàn)lask程序中使用WTForms實(shí)現(xiàn)的就是服務(wù)器驗(yàn)證,但是有些字段又會(huì)被渲染為HTML5的屬性,所以也不全是服務(wù)器驗(yàn)證。
這就是瀏覽器給出的驗(yàn)證提示
但是正則驗(yàn)證器,確實(shí)是在服務(wù)端完成驗(yàn)證的
Regexp(r'^[a-z0-9A-Z]+$',message='密碼只能有字母,數(shù)字,下劃線組成')
那么怎么在服務(wù)器驗(yàn)證數(shù)據(jù)呢,首先,我們的數(shù)據(jù)會(huì)提交到/
路徑,使用的是POST方法。
表單類對(duì)象loginform,有一個(gè)驗(yàn)證方法,loginform.validate()
,調(diào)用這個(gè)方法時(shí),會(huì)去調(diào)用你每一個(gè)字段中使用的每一個(gè)驗(yàn)證器去驗(yàn)證數(shù)據(jù),全部驗(yàn)證通過(guò)返回True,失敗返回False。
@app.route('/',methods=['GET','POST']) def login(): loginform = LoginForm() if request.method == 'GET': return render_template('login.html',form = loginform) elif request.method == 'POST' and loginform.validate(): return f'用戶 {loginform.username.data}登錄成功' else: return render_template('login.html',form = loginform)
- 如果請(qǐng)求方法時(shí)GET,直接渲染表單
- 如果請(qǐng)求方法時(shí)POST,并且
loginform.validate()==True
,表示驗(yàn)證通過(guò),這時(shí)候我們返回登錄成功,同時(shí)使用loginform.username.data
可以拿到用戶輸入的用戶名。 - 否則,驗(yàn)證失敗,再次渲染這個(gè)表單,注意:這時(shí)候,調(diào)用了
validate()
方法,返回False,產(chǎn)生了錯(cuò)誤信息,錯(cuò)誤信息在form.username.errors
,是一個(gè)列表,這時(shí)候login.html中的錯(cuò)誤信息列表就是有輸出了。
測(cè)試一下:我的密碼字段設(shè)置了正則驗(yàn)證,只允許輸入字母數(shù)字下劃線,而且字符個(gè)數(shù)在3-20個(gè)。
首先,不填寫字段,瀏覽器端會(huì)自動(dòng)驗(yàn)證
輸入正確格式的密碼:
輸入錯(cuò)誤格式的密碼:
到此這篇關(guān)于Flask表單與表單驗(yàn)證實(shí)現(xiàn)流程介紹的文章就介紹到這了,更多相關(guān)Flask表單內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python使用sort和class實(shí)現(xiàn)的多級(jí)排序功能示例
這篇文章主要介紹了Python使用sort和class實(shí)現(xiàn)的多級(jí)排序功能,涉及Python基于面向?qū)ο蟮脑乇闅v、列表排序、添加等相關(guān)操作技巧,需要的朋友可以參考下2018-08-08Python利用pangu模塊實(shí)現(xiàn)文本格式化小工具
其實(shí)使用pangu做文本格式標(biāo)準(zhǔn)化的業(yè)務(wù)代碼在之前就實(shí)現(xiàn)了,主要能夠?qū)⒅形奈谋疚臋n中的文字、標(biāo)點(diǎn)符號(hào)等進(jìn)行標(biāo)準(zhǔn)化。但是為了方便起來(lái)我們這里使用了Qt5將其做成了一個(gè)可以操作的頁(yè)面應(yīng)用,需要的可以了解一下2022-10-10Python 批量下載陰陽(yáng)師網(wǎng)站壁紙
學(xué)習(xí)要始于興趣,自己學(xué)習(xí)python的一大初衷是希望能用于寫一些簡(jiǎn)單的游戲腳本,能服務(wù)于生活。所以決定試著直接從爬取我最愛(ài)玩的陰陽(yáng)師網(wǎng)站的一些壁紙開始2021-05-05python的即時(shí)標(biāo)記項(xiàng)目練習(xí)筆記
這篇文章主要介紹了python的即時(shí)標(biāo)記項(xiàng)目練習(xí)筆記,本文是閱讀《python基礎(chǔ)教程》一書的動(dòng)手實(shí)踐項(xiàng)目,需要的朋友可以參考下2014-09-09Python中for循環(huán)可迭代對(duì)象迭代器及生成器源碼學(xué)習(xí)
這篇文章主要為大家介紹了Python中for循環(huán)可迭代對(duì)象迭代器及生成器的源碼學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05詳解Python利用configparser對(duì)配置文件進(jìn)行讀寫操作
這篇文章主要介紹了詳解Python利用configparser對(duì)配置文件進(jìn)行讀寫操作,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11