Flask五之表單

5、表單

一、Flask-WTF 擴展

Flask-WTF 及其依賴可以使用 pip 安裝:html

(venv) $ pip install flask-wtf

二、跨站請求僞造保護

【設置密鑰】flask

app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'

app.config 字典可用來存儲框架、 擴展和程序自己的配置變量。bootstrap

三、表單類

建立表單的三個步驟:瀏覽器

  • 定義Form的子類服務器

  • 在類裏添加字段session

  • 在字段裏添加驗證函數app

# Form 基類由 Flask-WTF 擴展定義
from flask_wtf import FlaskForm
# 字段直接從 WTForms 包中導入
from wtforms import StringField,SubmitField
# 驗證函數直接從 WTForms 包中導入
from wtforms.validators import DataRequired,Length

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

與其餘擴展的使用方法不一樣之處在於:
①不是實例化,而是繼承
②還須要從wtforms當中導入字段和驗證函數框架

【注意】
Form 基類由 Flask-WTF 擴展定義,因此從 flask_wtf 中導入。字段和驗證函數
卻能夠直接從 WTForms 包中導入。函數

四、把表單渲染成HTML

表單字段是可調用的,在模板中調用後會渲染成 HTML。假設視圖函數把一個
NameForm 實例經過參數 form傳入模板,在模板中能夠生成一個簡單的表單,
以下所示:ui

<form method="POST">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name() }}
{{ form.submit() }}
</form>

可使用Bootstrap 中預先定義好的表單樣式渲染整個 Flask-WTF 表單,
使用 Flask-Bootstrap,上述表單可以使用下面的方式渲染:

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

具體渲染方式以下:
【form.html】

{% 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 %}...{% endif %}。
若是條件的計算結果爲 True,那麼渲染 if 和 else 指令之間的值。若是條件的計算結果爲False,
則渲染else 和 endif 指令之間的值。在這個例子中,若是沒有定義模板變量 name,則會渲染字
符串「Hello,Stranger!」。內容區的第二部分使用 wtf.quick_form() 函數渲染NameForm 對象。

五、在視圖函數中處理表單

視圖函數 index() 不只要渲染表單,還要接收表單中的數據。

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

六、重定向和用戶會話

上面的視圖函數存在一個可用性問題。用戶輸入名字後提交表單,而後點擊瀏覽器
的刷新按鈕,會看到一個莫名其妙的警告,要求在再次提交表單以前進行確認:

之因此出現這種狀況,是由於刷新頁面時瀏覽器會從新發送以前已經發送過的最後
一個請求。若是這個請求是一個包含表單數據的 POST 請求,刷新頁面後會再次提
交表單。大多數狀況下,這並非理想的處理方式。不少用戶都不理解瀏覽器發出
的這個警告。基於這個緣由, 最好別讓 Web 程序把 POST 請求做爲瀏覽器發送的
最後一個請求。
這種需求的實現方式是, 使用**重定向**做爲 POST 請求的響應,而不是使用常規
響應。這個技巧稱爲 Post/ 重定向 /Get 模式。

程序能夠把數據存儲在** 用戶會話 **中,在請求之間「記住」數據。用戶會話是一
種私有存儲,存在於每一個鏈接服務器的客戶端中。 咱們在請求與響應中介紹過用戶
會話,它是請求上下文中的變量,名爲 ** session **,像標準的 Python 字典一
樣操做。
from flask import session
@app.route('/form2/',methods = ['GET','POST'])
def form2():
    form = NameForm()
    if form.validate_on_submit():
        session['name'] = form.name.data
        # 這裏也不須要設置form.name.data = '',
        # 由於已經重定向到別的url去了,下次再到這個界面會自動初始化爲''
        return redirect(url_for('hello'))
    return render_template('form.html',form = form, name = session.get('name'))

七、Flash消息

請求完成後,有時須要讓用戶知道狀態發生了變化。這裏可使用確認消息、警告或者
錯誤提醒。一個典型例子是,用戶提交了有一項錯誤的登陸表單後,服務器發回的響應
從新渲染了登陸表單,並在表單上面顯示一個消息,提示用戶用戶名或密碼錯誤。
經過Flask 的核心特性,** flash()函數 **可實現這種效果
from flask import flash
@app.route('/form3/',methods = ['GET','POST'])
def form3():
    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('you have changed your name')
        session['name'] = form.name.data
        return redirect(url_for('hello'))
    return render_template('form.html',form = form, name = session.get('name'))
僅調用 flash() 函數並不能把消息顯示出來,程序使用的模板要渲染這些消息。
最好在基模板中渲染 Flash消息,由於這樣全部頁面都能使用這些消息。 Flask 
把 get_flashed_messages() 函數開放給模板,用來獲取並渲染消息。

【base.html】

{% block content %}
<div class="container">
    {% 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 %}

在這個示例中,使用 Bootstrap 提供的警報 CSS 樣式渲染警告消息。
【注意】 在模板中使用循環是由於在以前的請求循環中每次調用 flash() 函數時都會生成一個消息,因此可能有多個消息在排隊等待顯示。 get_flashed_messages() 函數獲取的消息在下次調用時不會再次返回,所以 Flash消息只顯示一次,而後就消失了。

相關文章
相關標籤/搜索