Flask web表單 Flask-WTF表單擴展

  • 2019 年 12 月 19 日
  • 筆記

Web表單

web表單是web應用程式的基本功能。

它是HTML頁面中負責數據採集的部件。表單有三個部分組成:表單標籤、表單域、表單按鈕。表單允許用戶輸入數據,負責HTML頁面數據採集,通過表單將用戶輸入的數據提交給伺服器。

在Flask中,為了處理web表單,我們一般使用Flask-WTF擴展,它封裝了WTForms,並且它有驗證表單數據的功能。

安裝Flask-WTF擴展

pip3 install Flask-WTF

WTForms支援的HTML標準欄位

欄位對象

說明

StringField

文本欄位

TextAreaField

多行文本欄位

PasswordField

密碼文本欄位

HiddenField

隱藏文本欄位

DateField

文本欄位,值為datetime.date格式

DateTimeField

文本欄位,值為datetime.datetime格式

IntegerField

文本欄位,值為整數

DecimalField

文本欄位,值為decimal.Decimal

FloatField

文本欄位,值為浮點數

BooleanField

複選框,值為True和False

RadioField

一組單選框

SelectField

下拉列表

SelectMultipleField

下拉列表,可選擇多個值

FileField

文本上傳欄位

SubmitField

表單提交按鈕

FormField

把表單作為欄位嵌入另一個表單

FieldList

一組指定類型的欄位

WTForms常用驗證函數

驗證函數

說明

DataRequired

確保欄位中有數據

EqualTo

比較兩個欄位的值,常用於比較兩次密碼輸入

Length

驗證輸入的字元串長度

NumberRange

驗證輸入的值在數字範圍內

URL

驗證URL

AnyOf

驗證輸入值在可選列表中

NoneOf

驗證輸入值不在可選列表中

使用Flask-WTF需要配置參數SECRET_KEY。

CSRF_ENABLED是為了CSRF(跨站請求偽造)保護。 SECRET_KEY用來生成加密令牌,當CSRF激活的時候,該設置會根據設置的密匙生成加密令牌。

直接在HTML頁面寫form表單的示例

1. 在創建模板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.視圖函數中獲取表單數據:

from flask import Flask,render_template,request    # 創建Flask的app應用  app = Flask(__name__)    # index視圖函數  @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

訪問http://127.0.0.1:5000/login

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

直接使用HTML來寫表單可以實現提交資訊的效果。但是需要考慮這幾點,如果參數很多,後台也是需要一個個去校驗的,直接這樣去接受參數再校驗的話,這個工作量就會有些大。

而且還會出現csrf的攻擊問題,這時候就可以使用Flask-WTF來創建表單,避免這些問題。

使用Flask-WTF來編寫表單

1.編寫兩個視圖函數,以及form表單類,用於註冊以及跳轉index頁面

from flask import Flask, render_template, redirect, url_for, session  # 導入Flask-WTF表單  from flask_wtf import FlaskForm  # 導入表單所需要的欄位類型  from wtforms import StringField, PasswordField, SubmitField  # 導入表單的驗證器  from wtforms.validators import DataRequired, EqualTo    app = Flask(__name__)    # 設置密鑰,用於csrf_token的加解密  app.config["SECRET_KEY"] = "xhosd6f982yfhowefy29f"    # 定義表單的模型類  class RegisterForm(FlaskForm):      """自定義的註冊表單模型類"""      # DataRequired 保證數據必須填寫,並且不能為空      user_name = StringField(label="用戶名", validators=[DataRequired("用戶名不能為空")]) #  參數:名字,驗證器列表      password = PasswordField(label="密碼", validators=[DataRequired("密碼不能為空")])      password2 = PasswordField(label="確認密碼",validators=[DataRequired("確認密碼不能為空"),EqualTo("password", "兩次密碼不一致")])      submit = SubmitField(label="提交")    @app.route("/register", methods=["GET", "POST"])  def register():      # 創建表單對象, 如果是post請求,前端發送了數據,flask會把數據在構造form對象的時候,存放到對象中      form = RegisterForm()        # 判斷form中的數據是否合理      # 如果form中的數據完全滿足所有的驗證器,則返回真,否則返回假      if form.validate_on_submit():          # 表示驗證合格          # 提取數據          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

如果不填寫任何數據,則會提示如下:

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

正確填寫註冊資訊,查看是否正常跳至index頁面,如下:

自動驗證表單內容通過,並跳至index頁面。

從上面的示例可以看到,使用if form.validate_on_submit():就可以直接驗證所有欄位,可以省事多了。