Day03 Web表單

Day03 Web表單

源代碼: https://github.com/LToddy/blog

技術交流羣: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頁面:

templates/index.html

{% 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(陌生人)。

再來看一下視圖函數:

blog.py

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()的要求是,框框中的內容不爲空纔可以提交。
如果你什麼都沒寫,然後提交,就會出現:
類似這樣的情況。具體看每個人電腦的具體實現了。
還有一點,表單的提交要通過POST方法,這裏不再多餘說了,具體去看HTTP協議。

但是這個頁面還是有問題的,當你按下F5去刷新頁面的時候,會給你個提示:問你表單是不是要重新提交一下。
因爲頁面刷新會向瀏覽器重新發送最後一個請求,這裏的請求是提交表達,基於這個原因,我們利用重定向,來改成GET請求。

blog.py

@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中。怎麼理解呢?
瀏覽器是一個傻子,他只能記住最後發生的一件事情,這個session就是爲了強行讓瀏覽器記住一些東西。
還用到了redirect和url_for這兩個組合,url_for便於我們生成url,當然那一行代碼你也可以寫成:

redirect('/')

因爲就是要回到主頁嘛,主頁地址就是’/’,但是隨着程序日益的複雜,你不可能完全掌握所有的地址,所以我們通過url_for來獲得地址,url_for(‘index’)注意看括號中的參數內容’index’對應着視圖函數index()的名字。也就是說重新定向到這個函數映射的頁面上。

看一下完整代碼:

blog.py

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

blog.py

@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消息顯示出來

templates/base.html

{% block content %}
    {% for message in get_flashed_messages() %}
        <div class="alert alert-info">
            <button type="button" class="close" data-dismiss="alert">&times;</button>
            {{ message }}
        </div>
    {% endfor %}
    <div class="container">
        {% block page_content %}{% endblock %}
    </div>
{% endblock %}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章