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

一、跨站請求偽造保護
默認情況下,Flask-WTF能夠保護所有表單免受跨站請求偽造的攻擊。惡意網站把請求發送到被攻擊者已登錄的網站時就會引起CSRF攻擊。
為了實現CSRF保護,Flask-WTF需要程序設置一個密鑰。Flask-WTF使用這個密鑰生成加密令牌,再用令牌驗證請求中表單數據的真偽。設置密鑰的方法如下所示:
app = Flask(__name__) app.config['SECRET_KEY']='hard to guess string'
二、表單類
使用Flask-WTF時,每個web表單都由一個繼承自Form的類表示。這個定義表單中的一組字段,每個字段都用對象表示。字段對象可附屬一個或多個驗證函數。驗證函數用來驗證用戶提交的輸入值是否符合要求。
#!/usr/bin/env python
#簡單的web表單,包含一個文本字段和一個提交按鈕
from flask_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>元素。
WTForms支持的HTML標准字段
| 字段類型 | 說明 |
| StringField | 文本字段 |
| TextAreaField | 多行文本字段 |
| PasswordField | 密碼文本字段 |
| HiddenField | 隱藏文本字段 |
| DateField | 文本字段,值為datetime.date格式 |
| IntegerField | 文本字段,值為整數 |
| FloatField | 文本字段,值為浮點數 |
| SelectField | 下拉列表 |
| SubmitField | 表單提交按鈕 |
WTForms驗證函數
| 驗證函數 | 說明 |
| 驗證電子郵件地址 | |
| EqualTo | 比較兩個字段的值,常用於要求輸入兩次密碼進行確認的情況 |
| IPAddress | 驗證IPv4網絡地址 |
| Length | 驗證輸入字符串的長度 |
| NumberRange | 驗證輸入的值在數字范圍內 |
| Optional | 無輸入值時跳過其他驗證函數 |
| Required | 確保字段中有數據 |
| Regexp | 使用正則表達式驗證輸入值 |
| URL | 驗證URL |
| AnyOf | 確保輸入值在可選值列表中 |
| NoneOf | 確保輸入值不在可選值列表中 |
四、把表單渲染成HTML
表單字段是可用的,在模板中調用后會渲染成HTML。假設視圖函數把一個NameForm實例通過參數form傳入模板,在模板中可以生成一個簡單的表單,如下所示:
<form method="POST">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name() }}
{{ form.submit() }}
</form>
<form method="POST">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name(id='my-text-field') }}
{{ form.submit() }}
</form>
Flask-Bootstrap提供了一個非常高端的輔助函數,可以使用Bootstrap中預先定義好的表單樣式渲染整個Flask-WTF表單,而這些操作只需調用一次即可完成。
{% import "boostrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}
#使用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 %}
四、在視圖函數中處理表單
@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參數告訴Flask在URL映射中把這個視圖函數注冊為GET和POST請求的處理程序。如果沒指定methods參數,就只把視圖函數注冊為GET請求的處理程序。
五、重定向和用戶會話
#!/usr/bin/env python
from flask import Flask,render_template,session,redirect,url_for
app = Flask(__name__)
@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'))
六、Flash消息
例子:提示用戶名或密碼錯誤,彈出窗口
from flask import Flask,render_template,session,redirect,url_for,flash
app = Flask(__name__)
@app.route('/',methods=['GET','POST'])
def index():
form = NameForm()
if form.validata_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'))
#渲染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">×</button>
{{ message }}
</div>
{% endfor %}
{% block page_content %}{% endblock %}
</div>
{% endblock %}
