Python Flask Web 第十课 —— flask-wtf

1. Flask-WTF 的安装与密钥的设置

默认情况下,flask-wtf 能保护所有表单免受跨站请求伪造(Cross-site Request Forgery,CSRF)的攻击。恶意网站把请求发送到攻击者已登陆的其他网站时就会引发 CSRF 攻击。

flask-wtf 的安装如下:

pip install flask-wtf

为了实现 CSRF 保护,Flask-WTF 需要程序设置一个密钥,Flask-WTF 使用这个密钥生成加密令牌,再用令牌验证请求中表单数据的真伪。

设置密钥的方法如下所示:

app.config['SECRET_KEY'] = 'hard to guess'

app.config 字典可用来存储框架、扩展和程序本身的配置变量。

2. 表单类

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

from flask_wtf import Form
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired

class NameForm(Form):
    name = StringFiled('What is your name?', validators=[DataRequired()])
    submit = SubmitField('submit')
  • StringFiled 类表示属性为 type=”text” 的 <input> 元素。
  • SubmitField 类表示属性为 type=”submit” 的 <input> 元素。
  • DataRequired()确保提交的字段不为空。

3. 把表单渲染成 HTML

tempaltes/base.html

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

4. 在视图函数中处理表单

@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', name=name, form=form)

5. 重定向和用户会话

这里还存在一个可用性问题,就是用户输入名字后提交表单,然后点击浏览器的刷新按钮,会看到一个警告,要求在再次提交表单之前进行确认。之所以出现这种情况,是因为刷新页面时浏览器会重新发送之前已经发送过的最后一个请求。如果这个请求是一个包含表单数据的 POST 请求,刷新页面后会再次提交表单。当然,大部分情况下,这并非是最理想的处理方式。

基于此,最好不让 POST 作为浏览器发送的最后一个请求。

该需求的实现方式为,使用重定向作为 POST 请求的响应,而不是常规响应,重定向是一种特殊的响应,响应内容是 URL,而不是包含 HTML 代码的字符串。浏览器收到这种响应时,会向重定向的 URL 发起 GET 请求,显示页面内容,这个页面的加载可能要花几微妙,因为要先把第二个请求发送给服务器。除此之外,对用户透明(用户不会觉察有什么不同)。如此,便实现了最后一个请求是 GET 请求,所以刷新命令能像预期的那样正常使用了。该技术称为 POST/ 重定向 GET/模式

@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', name=session.get('name'), form=form)

6. 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('look like you have changed your name!')
        session['name'] = form.name.data
        return redirect(url_for('index'))
    return render_template('index.html', name=session.get('name'), form=form)

仅调用 flash() 函数并不能把消息显示出来,程序使用的模板要渲染这些消息。最好在基模板(templates/base.html)中渲染 flash 消息。这样所有页面均可使用这些消息。

{% block content %}
<div class="container">
    {% for message in get_flash_messages() %}
    <div classs="alert alert-warning">
    <button type="button" class="close" data_dismiss="alert">&times;</button>
    {{message}}
    </div>
    {% endfor %}
    {% block page_content %}{% endblock %}
</div>

{% endblock %}
发布了3759 篇原创文章 · 获赞 1676 · 访问量 1041万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览