Python Flask-web表单

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验证函数

验证函数

说明

Email

验证电子邮件地址

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏zcqshine's blog

springboot 获取form-data里的 file 文件小结

63860
来自专栏崔庆才的专栏

正则表达式中零宽断言的用法

了解了正则表达式,想必一般情况下的匹配都不会出现什么问题,但是如果一些特殊情况,可能需要用到一些更高级的正则表达式匹配操作,本节我们来说明一下正则表达式的一个较...

29640
来自专栏社区的朋友们

Java 动态加载 so 的解决方案

业务场景有对 so 实现动态加载/替换的需求,但 Java 并没有直接动态加载 so 的机制。本文将深度剖析 Java 加载 so 的实现机制,并提出一套 Ja...

1.8K10
来自专栏cmazxiaoma的架构师之路

JavaWeb学习(1) 使用Session和Token防止表单重复提交

21330
来自专栏小灰灰

报警系统QuickAlarm之频率统计及接口封装

前面将报警规则的制定加载解析,以及报警执行器的定义加载和扩展进行了讲解,基本上核心的内容已经完结,接下来剩下内容就比较简单了 报警频率的统计 报警线程池 对外封...

37380
来自专栏小樱的经验随笔

IPython使用学习笔记

学习《利用python进行数据分析》第三章 IPython:一种交互式计算和开发环境的笔记,共享给大家,同时为自己作为备忘用。 ? 安装ipython用pip即...

43850
来自专栏测试驿栈

Jmeter(三十一)_dummy sampler模拟数据驱动

之前写过一篇数据驱动的文章 数据驱动测试 ,但是内容过于简单,有些关键的地方没有写明白。这两天参照了一下官方文档,重新整理了一篇数据驱动测试!

37930
来自专栏逸鹏说道

Python3 与 C# 并发编程之~ 线程篇2

其实以前的 Linux中是没有线程这个概念的, Windows程序员经常使用线程,这一看~方便啊,然后可能是当时程序员偷懒了,就把进程模块改了改(这就是为什么之...

20440
来自专栏前端布道

全方位理解JavaScript的Event Loop

下面我们一个一个的来了解 Event Loop 相关的知识点,最后再一步一步分析出本段代码最后的输出顺序。

11130
来自专栏Seebug漏洞平台

34c3 部分Web Writeup

34c3应该算是2017年年末的最后一个惊喜了,比赛题目虽然有非预期导致难度降了很多,但是从CTF中能学到什么才是最重要的,其中Web有3个XSS题目,思路非常...

462100

扫码关注云+社区

领取腾讯云代金券