Web表單
web表單是web應(yīng)用程序的基本功能。
它是HTML頁面中負(fù)責(zé)數(shù)據(jù)采集的部件。表單有三個部分組成:表單標(biāo)簽、表單域、表單按鈕。表單允許用戶輸入數(shù)據(jù),負(fù)責(zé)HTML頁面數(shù)據(jù)采集,通過表單將用戶輸入的數(shù)據(jù)提交給服務(wù)器。
在Flask中,為了處理web表單,我們一般使用Flask-WTF擴展,它封裝了WTForms,并且它有驗證表單數(shù)據(jù)的功能。
安裝Flask-WTF擴展
pip3 install Flask-WTF
WTForms支持的HTML標(biāo)準(zhǔn)字段
| 字段對象 | 說明 |
|---|---|
| StringField | 文本字段 |
| TextAreaField | 多行文本字段 |
| PasswordField | 密碼文本字段 |
| HiddenField | 隱藏文本字段 |
| DateField | 文本字段,值為datetime.date格式 |
| DateTimeField | 文本字段,值為datetime.datetime格式 |
| IntegerField | 文本字段,值為整數(shù) |
| DecimalField | 文本字段,值為decimal.Decimal |
| FloatField | 文本字段,值為浮點數(shù) |
| BooleanField | 復(fù)選框,值為True和False |
| RadioField | 一組單選框 |
| SelectField | 下拉列表 |
| SelectMultipleField | 下拉列表,可選擇多個值 |
| FileField | 文本上傳字段 |
| SubmitField | 表單提交按鈕 |
| FormField | 把表單作為字段嵌入另一個表單 |
| FieldList | 一組指定類型的字段 |
WTForms常用驗證函數(shù)
| 驗證函數(shù) | 說明 |
|---|---|
| DataRequired | 確保字段中有數(shù)據(jù) |
| EqualTo | 比較兩個字段的值,常用于比較兩次密碼輸入 |
| Length | 驗證輸入的字符串長度 |
| NumberRange | 驗證輸入的值在數(shù)字范圍內(nèi) |
| URL | 驗證URL |
| AnyOf | 驗證輸入值在可選列表中 |
| NoneOf | 驗證輸入值不在可選列表中 |
使用Flask-WTF需要配置參數(shù)SECRET_KEY。
CSRF_ENABLED是為了CSRF(跨站請求偽造)保護。 SECRET_KEY用來生成加密令牌,當(dāng)CSRF激活的時候,該設(shè)置會根據(jù)設(shè)置的密匙生成加密令牌。
直接在HTML頁面寫form表單的示例
1. 在創(chuàng)建模板login.html頁面中直接寫form表單:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="post">
<input type="text" name="username" placeholder='Username'>
<input type="password" name="password" placeholder='password'>
<input type="submit">
</form>
{% if method == 'GET' %}
請求的方式:{{ method }}
{% elif method == 'POST' %}
請求的方式:{{ method }}
用戶名:{{ username }}
密碼: {{ password }}
{% endif %}
</body>
</html>
2.視圖函數(shù)中獲取表單數(shù)據(jù):
from flask import Flask,render_template,request
# 創(chuàng)建Flask的app應(yīng)用
app = Flask(__name__)
# index視圖函數(shù)
@app.route("/login",methods=['GET','POST'])
def login():
context = dict()
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
print(username, password)
context = {
'username': username,
'password': password,
}
context.update({'method': request.method})
return render_template('login.html', **context)
if __name__ == '__main__':
app.run(debug=True)
3.測試login

再次輸入用戶名和密碼直接提交如下:


直接使用HTML來寫表單可以實現(xiàn)提交信息的效果。但是需要考慮這幾點,如果參數(shù)很多,后臺也是需要一個個去校驗的,直接這樣去接受參數(shù)再校驗的話,這個工作量就會有些大。
而且還會出現(xiàn)csrf的攻擊問題,這時候就可以使用Flask-WTF來創(chuàng)建表單,避免這些問題。
使用Flask-WTF來編寫表單
1.編寫兩個視圖函數(shù),以及form表單類,用于注冊以及跳轉(zhuǎn)index頁面
from flask import Flask, render_template, redirect, url_for, session
# 導(dǎo)入Flask-WTF表單
from flask_wtf import FlaskForm
# 導(dǎo)入表單所需要的字段類型
from wtforms import StringField, PasswordField, SubmitField
# 導(dǎo)入表單的驗證器
from wtforms.validators import DataRequired, EqualTo
app = Flask(__name__)
# 設(shè)置密鑰,用于csrf_token的加解密
app.config["SECRET_KEY"] = "xhosd6f982yfhowefy29f"
# 定義表單的模型類
class RegisterForm(FlaskForm):
"""自定義的注冊表單模型類"""
# DataRequired 保證數(shù)據(jù)必須填寫,并且不能為空
user_name = StringField(label="用戶名", validators=[DataRequired("用戶名不能為空")]) # 參數(shù):名字,驗證器列表
password = PasswordField(label="密碼", validators=[DataRequired("密碼不能為空")])
password2 = PasswordField(label="確認(rèn)密碼",validators=[DataRequired("確認(rèn)密碼不能為空"),EqualTo("password", "兩次密碼不一致")])
submit = SubmitField(label="提交")
@app.route("/register", methods=["GET", "POST"])
def register():
# 創(chuàng)建表單對象, 如果是post請求,前端發(fā)送了數(shù)據(jù),flask會把數(shù)據(jù)在構(gòu)造form對象的時候,存放到對象中
form = RegisterForm()
# 判斷form中的數(shù)據(jù)是否合理
# 如果form中的數(shù)據(jù)完全滿足所有的驗證器,則返回真,否則返回假
if form.validate_on_submit():
# 表示驗證合格
# 提取數(shù)據(jù)
uname = form.user_name.data
pwd = form.password.data
pwd2 = form.password2.data
print(uname, pwd, pwd2)
session["user_name"] = uname
return redirect(url_for("index"))
return render_template("register.html", form=form)
@app.route("/index")
def index():
user_name = session.get("user_name", "")
return "hello %s" % user_name
if __name__ == '__main__':
app.run(debug=True)
2.編寫一個register.html模板,用于作為注冊頁面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="post">
{{ form.csrf_token }}
{{ form.user_name.label }}
<p>{{form.user_name}}</p>
{% for msg in form.user_name.errors %}
<p>{{msg}}</p>
{% endfor %}
{{ form.password.label }}
<p>{{form.password}}</p>
{% for msg in form.password.errors %}
<p>{{msg}}</p>
{% endfor %}
{{ form.password2.label }}
<p>{{form.password2}}</p>
{% for msg in form.password2.errors %}
<p>{{msg}}</p>
{% endfor %}
{{form.submit}}
</form>
</body>
</html>
3.登錄注冊頁面
訪問http://127.0.0.1:5000/register
如果不填寫任何數(shù)據(jù),則會提示如下:

填寫兩次密碼不一致,提示如下:


正確填寫注冊信息,查看是否正常跳至index頁面,如下:

自動驗證表單內(nèi)容通過,并跳至index頁面。
從上面的示例可以看到,使用if form.validate_on_submit():就可以直接驗證所有字段,可以省事多了。