Flask Web 开发 Chapter4 - Web 表单

处理Web表单的扩展 Flask-WTF

Flask-wtf 对WTForms包进行了包装,方便集成入Flask框架

跨站请求保护

CSRF(Cross-Site Request Forgery)是指恶意网站把请求发送到被攻击者已登录的其他网站就会引发CSRF攻击
为了实现CSRF保护,需要程序设置密钥,生成加密令牌,再用来验证表单数据真伪。非常简单:

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

不过在生产环境,不会直接写入程序,而会从文件或环境中导入配置值,Flask-wtf提供了方法来实现

表单类

使用Flask-wtf时,每一个表单都由一个继承自Form类表示,这个类定义表单的字段,每个字段由对象表示,
字段对象可以附属一个或多个验证函数,验证函数负责验证用户提交输入值是否符合要求
示范:

from flask.ext.wtf import Form
from wtforms import StringField,SubmitField
from wtforms.validators import DataRequired,Email

class NameForm(Form):
    name = StringField('what is your name ?',validators=[DataRequired()])
    email = StringField('what is your email ?',validators=[Email()])
    submit = SubmitField('Submit')

上面代码定义了3个字段:name,email,submit三个字段,name和email表示"text" 的input元素,
submit表示type = 'submit'的“input”元素。DataRequired接受用户输入之后,确保提交字段不为空,
Email确保输入为符合邮件的函数

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 比较2个字段值,一般用于输入2次密码进行确认情况
IPAddress 验证IPV4地址
Length 验证输入字符长度
Optional 无输入值时跳过其他验证函数
Required 确保字段有值
Regxp 使用正则表达式验证输入值
URL 验证URL
AnyOf 确保输入值在可选值列表中
NoneOf 确保输入值不在可选值列表

表单渲染成HTML

Flask-Bootstrap提供了一个辅助函数,使用Bootstrap预先定义好的表单样式渲染Flask-Wtf表单对象,使用Bootstrap默认样式渲染传入的表单。
还可以使视图函数渲染表单,接收表单数据

py:

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

html:

<div class="page-header">
    <h1>Hello, {% if name %}{{ name }}{% else %}Stranger{% endif %}!</h1>
</div>

{{ wtf.quick_form(form) }}

重定向和用户会话

如果使用上面的视图函数,重复点击链接会再次提交表单,让你确认。
不过可以重定向POST请求,重新向重定向的URL发起GET请求,显示页面内容 - POST/重定向/GET,模式
不过,处理POST请求时,如果不保存数据,下次请求来时,数据就已经丢失。
不过,可以通过用户会话(session)保存数据,并且像python字典一样操作

默认情况下,用户会话保存在cookie中,而且cookie使用SECRET_KEY加密

示范代码:

@app.route('/',methods=['GET','POST'])
def index():
    form = NameForm()
    if form.validate_on_submit():
        session['name'] = form.name.data
        session['email'] = form.email.data
        return redirect(url_for('index')) # url_for重定向必须是相应视图函数的名字
    return render_template('index.html',form=form,name=session.get('name'),email=session.get('email'))

Flash消息

如果状态发生变化,可以通过flash()通知用户 -确认消息,警告或者错误提醒 FLask的核心特性
不过仅仅调用flash()不能把消息显示,还需要模板渲染消息,最好在基模板渲染,这样所有页面都能使用。

py:

@app.route('/',methods=['GET','POST'])
def index():
    form = NameForm()
    if form.validate_on_submit():
        oldname = session['name']
        if oldname is not None and oldname!=form.name.data:
            flash('Looks like you have changed your name!')
        old_email = session['email']
        if  old_email is not None and old_email !=form.email.data:
            flash('Email changed!')
        session['name'] = form.name.data
        session['email'] = form.email.data
        return redirect(url_for('index')) # url_for重定向必须是相应视图函数的名字
    return render_template('index.html',form=form,name=session.get('name'),email=session.get('email'))

html:

{% for msg in get_flashed_messages() %}
        <div class="alert alert-warning">
            <button type="button" class="close" data-dismiss="alert">×</button>
            {{ msg }}
        </div>
{% endfor %}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,980评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,422评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,130评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,553评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,408评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,326评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,720评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,373评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,678评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,722评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,486评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,335评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,738评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,283评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,692评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,893评论 2 335

推荐阅读更多精彩内容

  • 22年12月更新:个人网站关停,如果仍旧对旧教程有兴趣参考 Github 的markdown内容[https://...
    tangyefei阅读 35,156评论 22 257
  • 第四章 Web表单 序:为什么需要Flask-wtf 第 2 章中介绍的请求对象包含客户端发出的所有请求信息。其中...
    科幻经典阅读 828评论 0 2
  • 请求对象包含客户端发出的所有请求信息。其中 request.form 能获取 POST 请求中提交的表单数据。 我...
    焉知非鱼阅读 1,113评论 0 2
  • 一、李家有女初长成 舜华是阁老李中彰的女儿,李中彰四十岁才得了这个女儿,本就对她多了几分怜爱。后来舜华十岁的时候,...
    蕲安阅读 1,416评论 6 12
  • 常用模拟 有时,不需要进行操作,也想模拟用户操作达到某些效果。比如在用户进入界面后就触发click事件,而不需要用...
    mytac阅读 1,238评论 5 5