Flask學(xué)習(xí)筆記-Web表單

表單類

一個簡單的 Web 表單,包含一個文本字段和一個提交按鈕中狂。
例如:
hello.py:定義表單類

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')

StringField類表示屬性為 type="text" 的 <input> 元素扑毡。SubmitField 類表示屬性為 type="submit" 的<input> 元素。字段構(gòu)造函數(shù)的第一個參數(shù)是把表單渲染成 HTML 時使用的標(biāo)號勋又。
StringField 構(gòu)造函數(shù)中的可選參數(shù) validators 指定一個由驗證函數(shù)組成的列表,在接受用戶提交的數(shù)據(jù)之前驗證數(shù)據(jù)换帜。驗證函數(shù) Required() 確保提交的字段不為空。


WTForms支持的HTML標(biāo)準(zhǔn)字段

WTForms驗證函數(shù)

把表單渲染成HTML

Flask-Bootstrap 提供了一個非常高端的輔助函數(shù),可以使用 Bootstrap 中預(yù)先定義好的表單樣式渲染整個 Flask-WTF 表單,而這些操作只需一次調(diào)用即可完成蹲嚣。使用 Flask-Bootstrap,上述表單可使用下面的方式渲染:

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

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

hello.py:路由方法

@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)

重定向和用戶會話

最新版的 hello.py 存在一個可用性問題隙畜。用戶輸入名字后提交表單,然后點(diǎn)擊瀏覽器的刷新按鈕,會看到一個莫名其妙的警告,要求在再次提交表單之前進(jìn)行確認(rèn)疲眷。之所以出現(xiàn)這種情況,是因為刷新頁面時瀏覽器會重新發(fā)送之前已經(jīng)發(fā)送過的最后一個請求您朽。如果這個請求是一個包含表單數(shù)據(jù)的 POST 請求,刷新頁面后會再次提交表單。
很多用戶都不理解瀏覽器發(fā)出的這個警告哗总。基于這個原因,最好別讓 Web 程序把 POST 請求作為瀏覽器發(fā)送的最后一個請求蛋哭。
這種需求的實現(xiàn)方式是,使用重定向作為 POST 請求的響應(yīng),而不是使用常規(guī)響應(yīng)涮母。重定向是一種特殊的響應(yīng),響應(yīng)內(nèi)容是 URL,而不是包含 HTML 代碼的字符串躁愿。瀏覽器收到這種響應(yīng)時,會向重定向的 URL 發(fā)起 GET 請求,顯示頁面的內(nèi)容沪蓬。這個頁面的加載可能要多花幾微秒,因為要先把第二個請求發(fā)給服務(wù)器。除此之外,用戶不會察覺到有什么不同∫荼ⅲ現(xiàn)在,最后一個請求是 GET 請求,所以刷新命令能像預(yù)期的那樣正常使用了云挟。這個技巧稱為 Post/ 重定向 /Get 模式。
但這種方法會帶來另一個問題园欣。程序處理 POST 請求時,使用 form.name.data 獲取用戶輸入的名字,可是一旦這個請求結(jié)束,數(shù)據(jù)也就丟失了。因為這個 POST 請求使用重定向處理,所以程序需要保存輸入的名字,這樣重定向后的請求才能獲得并使用這個名字,從而構(gòu)建真正的響應(yīng)狮暑。
程序可以把數(shù)據(jù)存儲在用戶會話中,在請求之間“記住”數(shù)據(jù)辉饱。用戶會話是一種私有存儲,存在于每個連接到服務(wù)器的客戶端中。我們在第 2 章介紹過用戶會話,它是請求上下文中的變量,名為 session,像標(biāo)準(zhǔn)的 Python 字典一樣操作缔逛。
hello.py:重定向和用戶會話

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'))

在程序的前一個版本中,局部變量 name 被用于存儲用戶在表單中輸入的名字姓惑。這個變量現(xiàn)在保存在用戶會話中,即 session['name'],所以在兩次請求之間也能記住輸入的值。
現(xiàn)在,包含合法表單數(shù)據(jù)的請求最后會調(diào)用 redirect() 函數(shù)敦冬。redirect() 是個輔助函數(shù),用來生成 HTTP 重定向響應(yīng)唯沮。redirect() 函數(shù)的參數(shù)是重定向的 URL,這里使用的重定向URL 是程序的根地址,因此重定向響應(yīng)本可以寫得更簡單一些,寫成 redirect('/'),但卻會使用 Flask 提供的 URL 生成函數(shù) url_for()。推薦使用 url_for() 生成 URL,因為這個函數(shù)使用 URL 映射生成 URL,從而保證 URL 和定義的路由兼容,而且修改路由名字后依然可用介蛉。
url_for() 函數(shù)的第一個且唯一必須指定的參數(shù)是端點(diǎn)名,即路由的內(nèi)部名字。默認(rèn)情況下,路由的端點(diǎn)是相應(yīng)視圖函數(shù)的名字践险。在這個示例中,處理根地址的視圖函數(shù)是index(),因此傳給 url_for() 函數(shù)的名字是 index。
最后一處改動位于 render_function() 函數(shù)中,使用 session.get('name') 直接從會話中讀取 name 參數(shù)的值巍虫。和普通的字典一樣,這里使用 get() 獲取字典中鍵對應(yīng)的值以避免未找到鍵的異常情況,因為對于不存在的鍵,get() 會返回默認(rèn)值 None。

Flash消息

一個典型例子是,用戶提交了有一項錯誤的登錄表單后,服務(wù)器發(fā)回的響應(yīng)重新渲染了登錄表單,并在表單上面顯示一個消息,提示用戶用戶名或密碼錯誤贰剥。
hello.py: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ù)開放給模板,用來獲取并渲染消息,如示例 4-7 所示。
示例 4-7 templates/base.html:渲染 Flash 消息

{% 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 %}

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蚜点,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌绍绘,老刑警劉巖奶镶,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異陪拘,居然都是意外死亡厂镇,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門左刽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捺信,“玉大人,你說我怎么就攤上這事欠痴∑浚” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵梨水,是天一觀的道長。 經(jīng)常有香客問我茵臭,道長,這世上最難降的妖魔是什么舅世? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任旦委,我火速辦了婚禮奇徒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘缨硝。我一直安慰自己摩钙,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布查辩。 她就那樣靜靜地躺著胖笛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宜岛。 梳的紋絲不亂的頭發(fā)上长踊,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機(jī)與錄音萍倡,去河邊找鬼身弊。 笑死,一個胖子當(dāng)著我的面吹牛列敲,可吹牛的內(nèi)容都是我干的阱佛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼戴而,長吁一口氣:“原來是場噩夢啊……” “哼凑术!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起所意,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤麦萤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后扁眯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體壮莹,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年姻檀,在試婚紗的時候發(fā)現(xiàn)自己被綠了命满。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡绣版,死狀恐怖胶台,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情杂抽,我是刑警寧澤诈唬,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站缩麸,受9級特大地震影響铸磅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一阅仔、第九天 我趴在偏房一處隱蔽的房頂上張望吹散。 院中可真熱鬧,春花似錦八酒、人聲如沸空民。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽界轩。三九已至,卻和暖如春衔瓮,著一層夾襖步出監(jiān)牢的瞬間浊猾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工报辱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留与殃,地道東北人。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓碍现,卻偏偏與公主長得像幅疼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子昼接,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 第四章 Web表單 序:為什么需要Flask-wtf 第 2 章中介紹的請求對象包含客戶端發(fā)出的所有請求信息爽篷。其中...
    科幻經(jīng)典閱讀 854評論 0 2
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)慢睡,斷路器逐工,智...
    卡卡羅2017閱讀 134,651評論 18 139
  • 22年12月更新:個人網(wǎng)站關(guān)停,如果仍舊對舊教程有興趣參考 Github 的markdown內(nèi)容[https://...
    tangyefei閱讀 35,180評論 22 257
  • 請求對象包含客戶端發(fā)出的所有請求信息漂辐。其中 request.form 能獲取 POST 請求中提交的表單數(shù)據(jù)泪喊。 我...
    焉知非魚閱讀 1,132評論 0 2
  • 第4章 Web表單 我們在第二章介紹過請求對象,它包含有客戶端請求的全部信息髓涯。尤其是袒啼,可以通過request.fo...
    易木成華閱讀 1,025評論 0 1