Flask表單

Bobbyby發表於2018-06-01

表單 flask-wtf 的使用

1.跨站請求偽造保護

Flask-WTF 能保護所有表單免受跨站請求偽造(Cross-Site Request Forgery,CSRF)的攻擊。

為了實現 CSRF 保護,Flask-WTF 需要程式設定一個金鑰。Flask-WTF 使用這個金鑰生成加密令牌,再用令牌驗證請求中表單資料的真偽。設定金鑰的方法如示例 4-1 所示。

# 如果要用flask_wtf模組, SECRET_KEY就必須設定 
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'

app.config 字典可用來儲存框架、擴充套件和程式本身的配置變數。使用標準的字典句法就能把配置值新增到 app.config 物件中。這個物件還提供了一些方法,可以從檔案或環境中匯入配置值。
SECRET_KEY 配置變數是通用金鑰,可在 Flask 和多個第三方擴充套件中使用。如其名所示,加密的強度取決於變數值的機密程度。不同的程式要使用不同的金鑰,而且要保證其他人不知道你所用的字串

2.表單類

使用 Flask-WTF 時,每個 Web 表單都由一個繼承自 Form 的類表示。這個類定義表單中的一組欄位,每個欄位都用物件表示。欄位物件可附屬一個或多個驗證函式。驗證函式用來驗證使用者提交的輸入值是否符合要求。

from flask.ext.wtf import Form
# 匯入表單類
from wtforms import StringField, SubmitField
# 匯入表單驗證類
from wtforms.validators import Required
class NameForm(Form):
 name = StringField('What is your name?', validators=[Required()])
 submit = SubmitField('Submit')

'what is your name? ' 是label validators中是表單驗證類,表單驗證類放在列表中

# 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驗證函式
Email  驗證電子郵件地址
EqualTo  比較兩個欄位的值;常用於要求輸入兩次密碼進行確認的情況
IPAddress  驗證 IPv4 網路地址
Length  驗證輸入字串的長度
NumberRange 驗證輸入的值在數字範圍內
Optional  無輸入值時跳過其他驗證函式
Required 確保欄位中有資料
Regexp  使用正規表示式驗證輸入值
URL  驗證 URL
AnyOf 確保輸入值在可選值列表中
NoneOf 確保輸入值不在可選值列表中

3.把表單渲染成HTML

表單欄位是可呼叫的,在模板中呼叫後會渲染成 HTML。

假設檢視函式把一個 NameForm 例項通過引數 form 傳入模板,在模板中可以生成一個簡單的表單,

簡單渲染

<form method="POST">
 {{ form.hidden_tag() }}
 {{ form.name.label }} {{ form.name(id='my-text-field') }}
 {{ form.submit() }}
</form>
#可以把引數傳入渲染欄位的函式,傳入的引數會被轉換成欄位的 HTML 屬性。例如,可以為欄位指定 id 或 class 屬性,然後定義 CSS 樣式:例如 form.name(id='my-text-field')

Bootstrap 渲染

可以使用 Bootstrap 中預先定義好的表單樣式渲染整個 Flask-WTF 表單

{% import "bootstrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}

wtf.quick_form() 函式的引數為 Flask-WTF 表單物件,使用 Bootstrap 的預設樣式渲染傳入的表單

4.在檢視函式中處理表單

檢視函式 index() 不僅要渲染表單,還要接收表單中的資料。

@app.route('/', methods=['GET', 'POST'])
def index():
    name = None
    form = NameForm()
    # 對傳回的資料進行對比校驗 
    if form.validate_on_submit():
        name = form.name.data
        # 將form中的資料清空
        form.name.data = ''
    return render_template('index.html', form=form, name=name)

5.重定向和使用者會話

為重新整理頁面時瀏覽器會重新傳送之前已經傳送過的最後一個請求.如果最後一個請求是個post請求, 會導致使用者體驗不好,使用重定向作為 POST 請求的響應,這個技巧稱為 Post/ 重定向 /Get 模式。

from flask import Flask, render_template, session, redirect, url_for

@app.route('/', methods=['GET', 'POST'])
def index():
    form = NameForm()
    if form.validate_on_submit():
        session['name'] = form.name.data
        return redirect(url_for('index'))
      
    return render_template('index.html', form=form, name=session.get('name'))
# 使用session.get('name') 當沒有時,返回none

6 Flash訊息

請求完成後,有時需要讓使用者知道狀態發生了變化。這裡可以使用確認訊息、警告或者錯誤提醒。

這種功能是 Flask 的核心特性。如示例 4-6 所示,flash() 函式可實現這種效果。

from flask import Flask, render_template, session, redirect, url_for, flash

@app.route('/', methods=['GET', 'POST'])
def index():
    form = NameForm()
    if form.validate_on_submit():
        old_name = session.get('name')
        # 當使用者傳回使用者名稱和session中的name不一樣時
        if old_name is not None and old_name != form.name.data:
            #如果兩個名字不一樣,就會呼叫 flash() 函式,在發給客戶端的下一個響應中顯示一個訊息。
            flash('Looks like you have changed your name!')
        session['name'] = form.name.data
        return redirect(url_for('index'))
    return render_template('index.html',form=form, name=session.get('name'))

Flask 把 get_flashed_messages() 函式開放給模板,用來獲取並渲染訊息

{% block content %}
    <div class="container">
        # 使用迴圈是因為在之前的請求迴圈中每次呼叫 flash() 函式時都會生成一個訊息
        {% for message in get_flashed_messages() %}
            <div class="alert alert-warning">
                <button type="button" class="close" data-dismiss="alert">&times;</button>
                {{ message }}
            </div>
        {% endfor %}
        {% block page_content %}{% endblock %}
    </div>
{% endblock %}

get_flashed_messages() 函式獲取的訊息在下次呼叫時不會再次返回,因此 Flash 訊息只顯示一次,然後就消失了。

相關文章