Flask表單與表單驗證實現(xiàn)流程介紹
表單介紹
說到表單,在HTML中表單的創(chuàng)建時通過<form>標簽實現(xiàn)的,在<form>標簽內(nèi)部,字段通過使用<input>標簽等定義。比如一個表單內(nèi)部有用戶名,密碼框這些,都是通過<input>,<label>標簽等實現(xiàn)的。
一個簡單的表單:

<form> First name:<br> <input type="text" name="firstname"> <br> Last name:<br> <input type="text" name="lastname"> </form>
將表單提交給服務端處理時,服務端需要驗證表單中的字段的取值是否符合要求。
在 Python 的 Web 開發(fā)中,表單內(nèi)部的字段標簽之類的,就不再使用HTML標簽來寫了,而是通過python類實現(xiàn)。
WTForms在python中使用類定義表單,然后直接通過類定義生成對應的HTML代碼,這種方式更加方便,而且使表單更易于重用。除非是非常簡單的程序,或者想讓表單的定義更加靈活,否則一般不會在模板中直接使用HTML代碼寫表單。
WTForms 和 Flask-WTF
WTForms 是一個靈活的表單驗證和表單渲染的庫,它的主要功能:
- 驗證表單中的字段的取值是否符合要求;
- 渲染輸出表單的 HTML 代碼
WTForms 可以與任意的 Web 框架和模板引擎一起使用。 在 Flask 框架或者 Django 框架中,都可以使用 WTForms。
Flask-WTF 在 WTForms 的基礎上提供了一些擴展,可以方便的在 Flask 框架中生成表單。
創(chuàng)建表單
下面直接用代碼講解如何創(chuàng)建表單。
首先,我們的目標是這樣一個頁面

一個簡單的登錄頁面,讓用戶輸入用戶名,密碼,同時對用戶名和密碼進行驗證,驗證成功就輸出,驗證不成功需要重新輸入,并提示錯誤信息。
首先,這是一個表單,表單內(nèi)有一些文本,有文本框,有登錄按鈕,這些都是通過python中的表單類創(chuàng)建的,使用的正是flask-wtf模塊創(chuàng)建的。
先導入需要的模塊
#導入表單類 from flask_wtf import FlaskForm #導入字段類 from wtforms import StringField,SubmitField,PasswordField #導入驗證器類 from wtforms.validators import DataRequired,Length,Regexp
class LoginForm(FlaskForm):
'''
這些字段對象會被渲染為html標簽
實例化一個文本字段對象,設置參數(shù)
label:這個值可以拿出來放在標簽前面顯示
validators=[]驗證器列表,實例化的驗證器對象,里面又可以設置參數(shù)
'''
#用戶名字段
username = StringField(
label='用戶名',
validators=[
DataRequired(message='用戶名不能為空'),
Length(3,20,message='用戶名長度在3-20個字符')
]
)
password = PasswordField(
label='密碼',
validators=[
DataRequired(message='密碼不能為空'),
Length(3,20,message='密碼長度在3-20個字符'),
Regexp(r'^[a-z0-9A-Z]+$',message='密碼只能有字母,數(shù)字,下劃線組成')
]
)
submit = SubmitField(label='登錄')我們創(chuàng)建了一個類LoginForm,它是一個表單類,繼承了FlaskForm,這個表單中包含一個用戶名username字段,密碼password字段,還有一個提交按鈕submit,這三個字段作為了類LoginForm的三個屬性。
表單字段
我們發(fā)現(xiàn)用戶名,密碼這些實際是文本框,既然不用HTML代碼實現(xiàn),那么怎么實現(xiàn)呢?
使用的就是WTForms中的各種字段類,比如這里:
username = StringField()
StringField()是WTForms 支持表單字段類,它表示文本字段,這樣一個字段會被渲染為
<input id="username" name="username" type="text" value="">
注意:實例化對象的名稱是username ,被渲染后的input標簽中的id和name屬性值都叫username
WTForms 支持如下類型的表單字段:

這只是一部分,還有很多其他支持的字段。
接著看代碼:
username = StringField(
label='用戶名',
validators=[
DataRequired(message='用戶名不能為空'),
Length(3,20,message='用戶名長度在3-20個字符')
]
)
驗證器
StringField類需要傳遞一些參數(shù):
label='用戶名' ,這個參數(shù)可以直接在模板頁面中顯示,使用form.username.label,把它放在文本框的前面,像下面這樣:

validators=[ ] 這個參數(shù)表示對這個字段使用的驗證器列表。驗證器就是對這個字段使用那些驗證,比如這里DataRequired,Length兩個驗證器類,同樣驗證器類需要實例化然后傳入?yún)?shù)。比如:
Length(3,20,message='用戶名長度在3-20個字符')
限定長度在3-20字符,如果驗證不通過,就彈出錯誤信息:message='用戶名長度在6-20個字符'。
驗證器也有很多類型,常見的驗證器類有:

還可以自定義驗證器類等等。
我們創(chuàng)建了一個單獨的文件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='用戶名長度在3-20個字符')
]
)
password = PasswordField(
label='密碼',
validators=[
DataRequired(message='密碼不能為空'),
Length(3,20,message='密碼長度在3-20個字符'),
Regexp(r'^[a-z0-9A-Z]+$',message='密碼只能有字母,數(shù)字,下劃線組成')
]
)
submit = SubmitField(label='登錄')
表單類創(chuàng)建好之后,可以做一個簡單的測試:
把這個表單顯示出來
首先,我們在app.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 攻擊,具體的我也不清楚,就不再細說了,總之需要設置
接著,在根路由下/,有視圖函數(shù)login,訪問這個路由的方法可以是GET,或者POST。首先假設是GET,我們就需要把之前的表單渲染出來,具體的做法就是:
使用創(chuàng)建的表單類LoginForm實例化一個表單對象loginform ,如果請求方法是GET,就去渲染login.html,然后表單對象作為參數(shù)傳遞過去。所以我們還需要設計一下login.html文件。
login.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登錄頁面</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>
這里使用了一個表格布局,然后表單的action="{{ url_for('login') }}" method="post",設置了表單的提交路徑,以及提交方法。
<td>{{ form.username.label }}</td>#拿到username的label值顯示出來
<td>{{ form.username }}</td>#顯示username這個字段
<td>{% for err in form.username.errors %}#這是錯誤信息,如果驗證不通過會顯示錯誤信息
{{ err }}
{% endfor %}
</td>最后,還要注意到: {{ form.hidden_tag() }}, 用于防范 CSRF 攻擊,生成 <input id=“csrf_token”/> 標簽??傊仨氁由希患由?,后面驗證數(shù)據(jù)的時候會出問題。
接著,運行app.py,訪問根路徑/,則是GET方法訪問,會渲染出login.html文件。

接著,我們需要實現(xiàn),用戶輸入數(shù)據(jù),我們進行驗證,驗證不成功就提示錯誤信息,驗證成功就登錄成功。
回到表單類中,我們可以發(fā)現(xiàn)使用的驗證器有這幾種:

其中,DataRequired,Length直接被渲染為HTML中input標簽的屬性:
maxlength="" minlength="" required

這時候驗證就是在瀏覽器上完成的了,而不是在服務器??蛻舳朔绞娇梢詫崟r動態(tài)的提示用戶輸入是否正確,只有用戶輸入正確后才會將表單數(shù)據(jù)發(fā)送給服務器??蛻舳蓑炞C可以增強用戶體驗,降低服務器負載。
參考書上說,F(xiàn)lask程序中使用WTForms實現(xiàn)的就是服務器驗證,但是有些字段又會被渲染為HTML5的屬性,所以也不全是服務器驗證。
這就是瀏覽器給出的驗證提示

但是正則驗證器,確實是在服務端完成驗證的
Regexp(r'^[a-z0-9A-Z]+$',message='密碼只能有字母,數(shù)字,下劃線組成')
那么怎么在服務器驗證數(shù)據(jù)呢,首先,我們的數(shù)據(jù)會提交到/路徑,使用的是POST方法。
表單類對象loginform,有一個驗證方法,loginform.validate(),調(diào)用這個方法時,會去調(diào)用你每一個字段中使用的每一個驗證器去驗證數(shù)據(jù),全部驗證通過返回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)
- 如果請求方法時GET,直接渲染表單
- 如果請求方法時POST,并且
loginform.validate()==True,表示驗證通過,這時候我們返回登錄成功,同時使用loginform.username.data可以拿到用戶輸入的用戶名。 - 否則,驗證失敗,再次渲染這個表單,注意:這時候,調(diào)用了
validate()方法,返回False,產(chǎn)生了錯誤信息,錯誤信息在form.username.errors,是一個列表,這時候login.html中的錯誤信息列表就是有輸出了。

測試一下:我的密碼字段設置了正則驗證,只允許輸入字母數(shù)字下劃線,而且字符個數(shù)在3-20個。
首先,不填寫字段,瀏覽器端會自動驗證

輸入正確格式的密碼:

輸入錯誤格式的密碼:

到此這篇關于Flask表單與表單驗證實現(xiàn)流程介紹的文章就介紹到這了,更多相關Flask表單內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python選擇網(wǎng)卡發(fā)包及接收數(shù)據(jù)包
今天小編就為大家分享一篇關于Python選擇網(wǎng)卡發(fā)包及接收數(shù)據(jù)包,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-04-04
淺談Python數(shù)學建模之數(shù)據(jù)導入
數(shù)據(jù)導入是所有數(shù)模編程的第一步,比你想象的更重要。Python 語言中數(shù)據(jù)導入的方法很多。對于數(shù)學建模問題編程來說,選擇什么方法最好呢?答案是:沒有最好的,只有最合適的。對于不同的問題,不同的算法,以及所調(diào)用工具包的不同實現(xiàn)方法,對于數(shù)據(jù)就會有不同的要求2021-06-06
django 將model轉(zhuǎn)換為字典的方法示例
平常的開發(fā)過程中不免遇到需要把model轉(zhuǎn)成字典的需求,這篇文章主要介紹了Django model轉(zhuǎn)字典的方法,非常具有實用價值,需要的朋友可以參考下2018-10-10
python urllib和urllib3知識點總結(jié)
在本篇內(nèi)容里小編給大家分享了一篇關于python urllib和urllib3知識點總結(jié)內(nèi)容,對此有興趣的朋友們可以學習參考下。2021-02-02
Python報錯之如何解決matplotlib繪圖中文顯示成框框問題
這篇文章主要介紹了Python報錯之如何解決matplotlib繪圖中文顯示成框框問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09
Python讀取Excel數(shù)據(jù)并生成圖表過程解析
這篇文章主要介紹了Python讀取Excel數(shù)據(jù)并生成圖表過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-06-06

