Day03 Web表單

源代碼: https://github.com/ltoddy/flask-tutorial

技術交流群:630398887(歡迎一起吹牛)

pip install flask-wtf

先看看一個普通的HTML頁面的表單的樣子:

<form action="">
    <label>你叫什么名字:<input type="text"></label><br>
    <input type="button" value="提交">
</form>

也就是說阿,在你要填寫的框框前有一個提示的標語(label),然后有一個提交的按鈕绍撞,按鈕上寫著提交倆字。

from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms import SubmitField

class NameForm(FlaskForm):
    name = StringField('你叫什么名字凑懂?') # 這里的'你叫什么名字硬贯?'就是對應的那個提示語
    # StringField() 就是那個輸入的框框
    submit = SubmitField('提交') # 這里的'提交'對應著按鈕的文字

先大體瀏覽一下下面兩個表格岛马,然后我在具體將使用

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 確保輸入值不在可選列表中

把表單加入到頁面中去:

順便提一句火惊,之前的那個hello_world函數求类,我把它改名為index了。
先看我們的html頁面:

<small>templates/index.html</small>

{% extends 'base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block page_content %}
    <div class="page-header">
        <h1>Hello {% if name %}{{ name }}{% else %}stranger!{% endif %}</h1>
    </div>
    {{ wtf.quick_form(form) }}
{% endblock %}

第二行:

{% import 'bootstrap/wtf.html' as wtf %}

bootstrap為我們集成好了一個宏(理解成函數就好了)矗晃,它可以很方便的把我們的表單類(剛才的NameForm)渲染成表單仑嗅。

再看下面:

{% <h1>Hello {% if name %}{{ name }}{% else %}stranger!{% endif %}</h1> %}

如果有名字近來,那么顯示名字张症,沒有名字的話就顯示stranger(陌生人)仓技。

再來看一下視圖函數:

<small>blog.py</small>

class NameForm(FlaskForm):
    name = StringField('你叫什么名字', validators=[Required()])
    submit = SubmitField('提交')
    

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

注意看,和剛才有差別俗他。
第一個是沒有那個validators=[Required()]這一部分的脖捻,這段是什么意思呢,就是說你在框框中填寫的內容是有要求的兆衅,這個Required()的要求是地沮,框框中的內容不為空才可以提交。
如果你什么都沒寫羡亩,然后提交摩疑,就會出現(xiàn):


類似這樣的情況。具體看每個人電腦的具體實現(xiàn)了畏铆。
還有一點雷袋,表單的提交要通過POST方法,這里不再多余說了辞居,具體去看HTTP協(xié)議楷怒。

但是這個頁面還是有問題的,當你按下F5去刷新頁面的時候瓦灶,會給你個提示:問你表單是不是要重新提交一下鸠删。
因為頁面刷新會向瀏覽器重新發(fā)送最后一個請求,這里的請求是提交表達贼陶,基于這個原因刃泡,我們利用重定向巧娱,來改成GET請求。

<small>blog.py</small>

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

這里我用到了一個東西:session(會話)捅僵,它會記住上下文家卖,把數據存儲在這個session中。怎么理解呢庙楚?
瀏覽器是一個傻子,他只能記住最后發(fā)生的一件事情趴樱,這個session就是為了強行讓瀏覽器記住一些東西馒闷。
還用到了redirect和url_for這兩個組合,url_for便于我們生成url,當然那一行代碼你也可以寫成:

redirect('/')

因為就是要回到主頁嘛叁征,主頁地址就是'/'纳账,但是隨著程序日益的復雜,你不可能完全掌握所有的地址捺疼,所以我們通過url_for來獲得地址疏虫,url_for('index')注意看括號中的參數內容'index'對應著視圖函數index()的名字。也就是說重新定向到這個函數映射的頁面上啤呼。

看一下完整代碼:

<small>blog.py</small>

from flask import Flask
from flask import render_template
from flask import redirect
from flask import url_for
from flask import session
from flask_bootstrap import Bootstrap
from flask_script import Manager
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms import SubmitField
from wtforms.validators import Required

app = Flask(__name__)
app.config['SECRET_KEY'] = 'a string' # 這一行是必須要加上的卧秘,為了防止CRSF攻擊
bootstrap = Bootstrap(app)
manager = Manager(app)


class NameForm(FlaskForm):
    name = StringField('你叫什么名字', validators=[Required()])
    submit = SubmitField('提交')


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


@app.route('/<username>')
def user(username):
    return render_template('user.html', name=username)


@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404


@app.errorhandler(500)
def internal_server_error(e):
    return render_template('500.html'), 500


if __name__ == '__main__':
    manager.run()

再介紹一點更人性化的東西:

Flash消息:

有些時候,當你作出了改動的時候官扣,最好有個東西來提醒你:Flash

<small>blog.py</small>

@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('你更改了名字')
        session['name'] = form.name.data
        form.name.data = ''
        return redirect(url_for('index'))
    return render_template('index.html', name=session.get('name', None), form=form)

需要再更改一下我們的模板翅敌,讓flash消息顯示出來

<small>templates/base.html</small>

{% block content %}
    {% for message in get_flashed_messages() %}
        <div class="alert alert-info">
            <button type="button" class="close" data-dismiss="alert">×</button>
            {{ message }}
        </div>
    {% endfor %}
    <div class="container">
        {% block page_content %}{% endblock %}
    </div>
{% endblock %}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市惕蹄,隨后出現(xiàn)的幾起案子蚯涮,更是在濱河造成了極大的恐慌,老刑警劉巖卖陵,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件遭顶,死亡現(xiàn)場離奇詭異,居然都是意外死亡泪蔫,警方通過查閱死者的電腦和手機棒旗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸥滨,“玉大人嗦哆,你說我怎么就攤上這事⌒鲎遥” “怎么了老速?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長凸主。 經常有香客問我橘券,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任旁舰,我火速辦了婚禮锋华,結果婚禮上,老公的妹妹穿的比我還像新娘箭窜。我一直安慰自己毯焕,他們只是感情好,可當我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布磺樱。 她就那樣靜靜地躺著纳猫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪竹捉。 梳的紋絲不亂的頭發(fā)上芜辕,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天,我揣著相機與錄音块差,去河邊找鬼侵续。 笑死,一個胖子當著我的面吹牛憨闰,可吹牛的內容都是我干的状蜗。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼起趾,長吁一口氣:“原來是場噩夢啊……” “哼诗舰!你這毒婦竟也來了?” 一聲冷哼從身側響起训裆,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤眶根,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后边琉,有當地人在樹林里發(fā)現(xiàn)了一具尸體属百,經...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年变姨,在試婚紗的時候發(fā)現(xiàn)自己被綠了族扰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡定欧,死狀恐怖渔呵,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情砍鸠,我是刑警寧澤扩氢,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站爷辱,受9級特大地震影響录豺,放射性物質發(fā)生泄漏朦肘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一双饥、第九天 我趴在偏房一處隱蔽的房頂上張望媒抠。 院中可真熱鬧,春花似錦咏花、人聲如沸趴生。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冲秽。三九已至,卻和暖如春矩父,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背排霉。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工窍株, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人攻柠。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓球订,卻偏偏與公主長得像,于是被迫代替她去往敵國和親瑰钮。 傳聞我的和親對象是個殘疾皇子冒滩,可洞房花燭夜當晚...
    茶點故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內容