DAY3-Flask

Flask-WTF扩展可以把处理Web表单的过程变成一种愉悦的体验。

安装命令

pip install flask-wtf

跨站请求伪造保护

Flask-WTF能保护所有表单免受跨站请求伪造(CSRF)的攻击。恶意网站把请求发送到被攻击者已登录的其他网站时就会引发CSRF攻击。
为了实现CSRF,Flask-WTF需要程序设置一个密钥。Flask-WTF使用这个密钥生成加密令牌,再用令牌验证请求中表单数据的真伪。

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

app.config字典可用来存储框架、扩展和程序本身的配置变量。使用标准的字典句法就能把配置值添加到app.config对象中。

表单类

使用Flask-WTF时,每个Web表单都由一个继承自Form的类表示。这个类定义表单中的一组字段,每个字段都用对象表示。字段对象可附属一个或多个验证函数。验证函数用来验证用户提交的输入值是否符合标准。

定义表单类
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired


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

字段构造函数的第一个参数是把表单渲染成HTML时使用的标号。
StringField构造函数中的可选参数validators指定一个由验证函数组成的列表,在接受用户提交的数据之前验证数据。验证函数DataRequired()确保提交的字段不为空。

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 确保输入值不在可选值列表中

把表单渲染成HTML

表单字段是可调用的,在模板中调用后会渲染成HTML。
import指令允许导入模板中的元素并用在多个模板中。导入的bootstrap/wtf.html文件中定义了一个使用Bootstrap渲染Flask-WTF表单对象的辅助函数。wtf.quick_from()函数的参数为Flask-WTF表单对象,使用Bootstrap的默认样式渲染传入的表单。

使用Flask-WTF和Flask-Bootstrap渲染表单
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}

{% block title %}Flasky{% endblock %}

{% block page_content%}

{{wtf.quick_form(form)}}
{% endblock %}

Jinja2中的条件语句格式为{% if condition %}...{% else %}...{% elseif %}

在视图函数中处理表单

路由方法
@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请求的处理程序。

重定向和用户会话

重定向是一种特殊的相应,响应内容是URL,而不是包含HTML代码的字符串。这个技巧称为 POST/重定向/GET模式。

用户对话是一种私有存储,存在于每个连接到服务器的客户端中。用户会话是请求上下文中的变量,名为session
默认情况下,用户会话保存在客户端cookie中,使用设置的SECRET_KEY进行加密签名。如果篡改了cookie中的内容,签名就会失效,会话也会随之失效。

重定向和用户会话
from flask import Flask, render_template, session, redirect, url_for

@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'))

redirect()是个辅助函数,用来生成HTTP重定向响应。redirect()函数的参数是重定向的URL,这里使用的重定向URL是程序的跟地址。
url_for()函数使用URL映射生成URL,从而保证URL和定义的路由兼容,而且修改路由名字后依然可用。
url_for()函数的第一个且唯一必须指定的参数是端点名,即路由的内部名字。路由的端点是相应视图函数的名字。
使用get()获取字典中键对应的值以避免未找到键的异常情况,因为对于不存在的值,get()会返回默认值None。

Flash消息

Flash消息
from flask import Flask, render_template, session, redirect, url_for, flash

@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('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()函数并不能把消息显示出来,程序使用的模板要渲染这些消息。最好在基模板中渲染Flash消息,因为这样所有页面都能使用这些消息。Flask把get_flashed_messages()函数开放给模板,用来获取并渲染消息。

渲染Flash消息
{% for message in get_flashed_messages() %}
    
{{ message}}
{% endfor %} {% block page_content %}{% endblock %}

在模板中使用循环是因为之前的请求循环中每次调用flash()函数时都会生成一个消息,所以可能有多个消息在排队等待显示。get_flashed_messages()函数获取的消息在下次调用时不会再次返回,因此Flash消息只显示一次,然后就消失了。

你可能感兴趣的:(DAY3-Flask)