DAY3-Flask

Flask-WTF擴展可以把處理Web表單的過程變成一種愉悅的體驗。

安裝命令

pip install flask-wtf

跨站請求偽造保護

Flask-WTF能保護所有表單免受跨站請求偽造(CSRF)的攻擊。惡意網(wǎng)站把請求發(fā)送到被攻擊者已登錄的其他網(wǎng)站時就會引發(fā)CSRF攻擊。
為了實現(xiàn)CSRF,F(xiàn)lask-WTF需要程序設(shè)置一個密鑰。Flask-WTF使用這個密鑰生成加密令牌,再用令牌驗證請求中表單數(shù)據(jù)的真?zhèn)巍?/p>

設(shè)置Flask-WTF
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'

app.config字典可用來存儲框架、擴展和程序本身的配置變量。使用標準的字典句法就能把配置值添加到app.config對象中。

表單類

使用Flask-WTF時,每個Web表單都由一個繼承自Form的類表示。這個類定義表單中的一組字段,每個字段都用對象表示。字段對象可附屬一個或多個驗證函數(shù)。驗證函數(shù)用來驗證用戶提交的輸入值是否符合標準。

定義表單類
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired


class NameForm(Form):
    name = StringField('What is your name?', validators=[DataRequired()])
    submit = SubmitField('Submit')

字段構(gòu)造函數(shù)的第一個參數(shù)是把表單渲染成HTML時使用的標號。
StringField構(gòu)造函數(shù)中的可選參數(shù)validators指定一個由驗證函數(shù)組成的列表,在接受用戶提交的數(shù)據(jù)之前驗證數(shù)據(jù)。驗證函數(shù)DataRequired()確保提交的字段不為空。

WTForms支持的HTML標準字段
字段類型 說明
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ù) 說明
Email 驗證電子郵件地址
EqualTo 比較兩個字段的值;常用于要求輸入兩次密碼進行確認的情況
IPAddress 驗證IPv4網(wǎng)絡(luò)地址
Length 驗證輸入字符串的長度
NumberRange 驗證輸入的值在數(shù)字范圍內(nèi)
Optional 無輸入時跳過其他驗證函數(shù)
Required 確保字段中有數(shù)據(jù)
Regexp 使用正則表達式驗證輸入值
URL 驗證URL
AnyOf 確保輸入值在可選值列表中
NoneOf 確保輸入值不在可選值列表中

把表單渲染成HTML

表單字段是可調(diào)用的,在模板中調(diào)用后會渲染成HTML。
import指令允許導(dǎo)入模板中的元素并用在多個模板中。導(dǎo)入的bootstrap/wtf.html文件中定義了一個使用Bootstrap渲染Flask-WTF表單對象的輔助函數(shù)。wtf.quick_from()函數(shù)的參數(shù)為Flask-WTF表單對象,使用Bootstrap的默認樣式渲染傳入的表單。

使用Flask-WTF和Flask-Bootstrap渲染表單
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}

{% block title %}Flasky{% endblock %}

{% block page_content%}
<div class="page-header">
   <h1>Hello,{% if name %}{{name}}{% else %}Stranger{% endif %}!</h1>
</div>
{{wtf.quick_form(form)}}
{% endblock %}

Jinja2中的條件語句格式為{% if condition %}...{% else %}...{% elseif %}。

在視圖函數(shù)中處理表單

路由方法
@app.route('/', methods=['GET', 'POST'])
def index():
    name = None
    form = NameForm()
    if form.validate_on_submit():
        name = form.name.data
        form.name.data = ''
    return render_template('index.html', form=form, name=name)

app.route修飾器中添加的methods參數(shù)告訴Flask在URL映射中把這個視圖函數(shù)注冊為GET和POST請求的處理過程。如果沒指定methods參數(shù),就只把視圖函數(shù)注冊為GET請求的處理程序。

重定向和用戶會話

重定向是一種特殊的相應(yīng),響應(yīng)內(nèi)容是URL,而不是包含HTML代碼的字符串。這個技巧稱為 POST/重定向/GET模式。

用戶對話是一種私有存儲,存在于每個連接到服務(wù)器的客戶端中。用戶會話是請求上下文中的變量,名為session。
默認情況下,用戶會話保存在客戶端cookie中,使用設(shè)置的SECRET_KEY進行加密簽名。如果篡改了cookie中的內(nèi)容,簽名就會失效,會話也會隨之失效。

重定向和用戶會話
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'))

redirect()是個輔助函數(shù),用來生成HTTP重定向響應(yīng)。redirect()函數(shù)的參數(shù)是重定向的URL,這里使用的重定向URL是程序的跟地址。
url_for()函數(shù)使用URL映射生成URL,從而保證URL和定義的路由兼容,而且修改路由名字后依然可用。
url_for()函數(shù)的第一個且唯一必須指定的參數(shù)是端點名,即路由的內(nèi)部名字。路由的端點是相應(yīng)視圖函數(shù)的名字。
使用get()獲取字典中鍵對應(yīng)的值以避免未找到鍵的異常情況,因為對于不存在的值,get()會返回默認值None。

Flash消息

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')
        if old_name is not None and old_name != form.name.data:
            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'))

僅調(diào)用flash()函數(shù)并不能把消息顯示出來,程序使用的模板要渲染這些消息。最好在基模板中渲染Flash消息,因為這樣所有頁面都能使用這些消息。Flask把get_flashed_messages()函數(shù)開放給模板,用來獲取并渲染消息。

渲染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 %}

在模板中使用循環(huán)是因為之前的請求循環(huán)中每次調(diào)用flash()函數(shù)時都會生成一個消息,所以可能有多個消息在排隊等待顯示。get_flashed_messages()函數(shù)獲取的消息在下次調(diào)用時不會再次返回,因此Flash消息只顯示一次,然后就消失了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容