Flask表單處理:WTForms字段與表單提交

在Web開發中,表單是用戶與應用交互的重要方式,比如用戶註冊、登錄、提交評論等功能都依賴表單。Flask本身沒有內置表單處理功能,但藉助Flask-WTF擴展(基於WTForms庫),我們可以輕鬆實現表單的定義、驗證和提交。本文將從基礎開始,帶你掌握Flask中使用WTForms處理表單的核心知識點。

一、安裝依賴

首先,需要安裝Flask-WTF擴展(它已集成了WTForms,無需單獨安裝)。打開命令行,執行:

pip install flask-wtf

二、WTForms常用字段類型

WTForms提供了多種預定義的字段類型,對應HTML的不同輸入控件。以下是初學者最常用的幾種:

WTForms字段 HTML對應類型 功能描述
StringField <input type="text"> 單行文本輸入(如用戶名、郵箱)
PasswordField <input type="password"> 密碼輸入(自動隱藏輸入內容)
SubmitField <input type="submit"> 提交按鈕
IntegerField <input type="number"> 整數輸入
BooleanField <input type="checkbox"> 複選框(True/False值)
RadioField <input type="radio"> 單選按鈕組
SelectField <select> 下拉菜單

三、定義表單類

在Flask中,我們通過繼承FlaskForm定義表單,並在類中聲明具體字段。例如,創建一個簡單的登錄表單:

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Length, Email  # 導入驗證器

class LoginForm(FlaskForm):
    # 用戶名:標籤爲“用戶名”,必填(DataRequired),長度3-20字符(Length)
    username = StringField('用戶名', validators=[
        DataRequired(message='用戶名不能爲空'),
        Length(min=3, max=20, message='用戶名長度需3-20字符')
    ])
    # 郵箱:標籤爲“郵箱”,必填且格式驗證(Email)
    email = StringField('郵箱', validators=[
        DataRequired(message='郵箱不能爲空'),
        Email(message='請輸入有效的郵箱地址')
    ])
    # 密碼:標籤爲“密碼”,必填
    password = PasswordField('密碼', validators=[
        DataRequired(message='密碼不能爲空')
    ])
    # 提交按鈕
    submit = SubmitField('登錄')

關鍵點
- FlaskFormFlask-WTF提供的基類,繼承它即可創建表單。
- validators參數用於定義字段驗證規則(如必填、長度限制、格式驗證),DataRequired表示字段不能爲空,Email驗證郵箱格式。
- 字段名(如username)是Python變量名,標籤字符串(如’用戶名’)會在模板中顯示。

四、視圖函數處理表單

表單需要在視圖函數中處理GET(首次加載)POST(提交數據)兩種請求。核心步驟:
1. 創建表單實例。
2. 檢查是否爲POST請求且數據驗證通過(form.validate_on_submit())。
3. 驗證通過則處理數據(如保存到數據庫);否則顯示錯誤信息。

示例代碼:

from flask import Flask, render_template, redirect, url_for
from forms import LoginForm  # 導入剛纔定義的LoginForm

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key-here'  # 必須設置,用於CSRF保護(生產環境需隨機複雜密鑰)

@app.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()  # 創建表單實例
    if form.validate_on_submit():  # 檢查是否爲POST且數據合法
        # 獲取表單數據(通過.data屬性)
        username = form.username.data
        email = form.email.data
        password = form.password.data
        # 這裏可以處理數據(如驗證登錄、保存用戶信息)
        print(f"用戶登錄:{username}, {email}")
        return redirect(url_for('success'))  # 提交成功後跳轉
    return render_template('login.html', form=form)  # 渲染模板,傳遞表單對象

@app.route('/success')
def success():
    return "登錄成功!"

if __name__ == '__main__':
    app.run(debug=True)

五、模板渲染表單

模板需要渲染表單,並處理提交和錯誤信息。使用Flask-WTF的模板工具可以簡化表單渲染,核心是:
- form.hidden_tag():自動生成CSRF保護令牌(必須添加,否則表單提交會被攔截)。
- 循環form.errors顯示錯誤信息。

創建templates/login.html

<!DOCTYPE html>
<html>
<head>
    <title>用戶登錄</title>
    <style>
        .error { color: red; }  /* 錯誤信息樣式 */
        .form-group { margin-bottom: 10px; }
    </style>
</head>
<body>
    <h1>用戶登錄</h1>
    <!-- 渲染表單,提交方式爲POST -->
    <form method="post">
        {{ form.hidden_tag() }}  <!-- CSRF保護令牌 -->

        <!-- 用戶名 -->
        <div class="form-group">
            {{ form.username.label }}<br>
            {{ form.username(size=30) }}  <!-- 生成<input type="text"> -->
            {% for error in form.username.errors %}
                <span class="error">{{ error }}</span>  <!-- 顯示錯誤信息 -->
            {% endfor %}
        </div>

        <!-- 郵箱 -->
        <div class="form-group">
            {{ form.email.label }}<br>
            {{ form.email(size=30) }}
            {% for error in form.email.errors %}
                <span class="error">{{ error }}</span>
            {% endfor %}
        </div>

        <!-- 密碼 -->
        <div class="form-group">
            {{ form.password.label }}<br>
            {{ form.password(size=30) }}
            {% for error in form.password.errors %}
                <span class="error">{{ error }}</span>
            {% endfor %}
        </div>

        <!-- 提交按鈕 -->
        {{ form.submit() }}
    </form>
</body>
</html>

關鍵點
- form.hidden_tag()會生成一個隱藏的<input>標籤,用於CSRF防護,必須包含。
- form.username.label生成字段標籤(如“用戶名”),form.username(size=30)生成文本輸入框。
- form.errors是一個字典,存儲每個字段的錯誤信息,通過循環顯示。

六、核心原理總結

  1. 表單定義:通過FlaskForm子類聲明字段和驗證規則。
  2. 請求處理:視圖函數區分GET(顯示空表單)和POST(驗證提交數據)。
  3. 數據驗證form.validate_on_submit()自動運行所有驗證器(必填、格式等),通過後獲取數據。
  4. 模板渲染form對象自動生成HTML表單元素,結合模板循環顯示錯誤信息。
  5. CSRF保護form.hidden_tag()生成令牌,防止跨站請求僞造攻擊。

七、常見問題與解決

  • “CSRF token missing”錯誤:確保form.hidden_tag()在模板中,且app.config['SECRET_KEY']已設置。
  • 表單驗證不通過:檢查validators是否正確配置,錯誤信息在form.errors中。
  • 密碼輸入未隱藏:使用PasswordField而非StringField,它會自動渲染爲<input type="password">

通過以上步驟,你已掌握Flask表單處理的核心:定義字段、處理請求、驗證數據和渲染表單。後續可結合數據庫(如SQLAlchemy)存儲表單數據,或添加更多字段類型(如單選按鈕、下拉菜單)實現複雜交互。

小夜