Flask学习之三——Web表单

1. CSRF 保护

from flask import Flask

app = Flask(__name__)
app.config[‘SECRET_KEY‘] = ‘secret_key string‘

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

ps:为了增强安全性,密钥不应该直接写入代码,而要保存在环境变量中

2.  表单类

When using Flask-WTF, each web form is represented by a class that inherits from class Form.
The class defines the list of fields in the form, each represented by an object.
Eachfield object can have one or more validators attached; validators are functions that check whether the input submitted by the user is valid.

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

class NameForm(Form):
    name = StringField(‘What is your name?‘, validators=[Required(), Length(1, 16)])
    submit = SubmitField(‘Submit‘)

The StringField class represents an <input> element with a type="text" attribute.
The SubmitField class represents an <input> element with a type="submit" attribute.
The first argument to the field constructors is the label that will be used when rendering the form to HTML.
The optional validators argument included in the StringField constructor defines a list of checkers that will be applied to the data submitted by the user before it is accepted.
The Required() validator ensures that the field is not submitted empty.

wtforms Standard HTML fields

wtforms validators

3. 把表单渲染成HTML

假设视图函数把一个 NameForm 实例通过参数 form 传入模板,在模板中可以生成一个简单的表单,如下所示

<form method="Post">
    {{ form.name.label }}{{ form.name() }}
    {{ form.submit() }}
</form>

To improve the look of the form, any arguments sent into the calls that render the fields are converted into HTML attributes for the field;
so, for example, you can give the field id or class attributes and then define CSS styles:

<form method="POST">
    {{ form.name.label }} {{ form.name(id=‘my-text-field‘) }}
    {{ form.submit() }}
</form>

Flask-Bootstrap可以使用 Bootstrap 中预先定义好的表单样式渲染整个 Flask-WTF 表单

{% import "bootstrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}

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

app.route 修饰器中添加的 methods 参数告诉 Flask 在 URL 映射中把这个视图函数注册为GET 和 POST 请求的处理程序。如果没指定 methods 参数,就只把视图函数注册为 GET 请求的处理程序。
提交表单后,如果数据能被所有验证函数接受,那么 validate_on_submit() 方法的返回值为 True,否则返回 False。这个函数的返回值决定是重新渲染表单还是处理表单提交的数据。

用户第一次访问程序时,服务器会收到一个没有表单数据的 GET 请求,所以 validate_on_submit() 将返回 False。
if 语句的内容将被跳过,通过渲染模板处理请求,并传入表单对象和值为 None 的 name 变量作为参数。用户会看到浏览器中显示了一个表单。
用户提交表单后,服务器收到一个包含数据的 POST 请求。validate_on_submit() 会调用name 字段上附属的 Required() 验证函数。
如果名字不为空,就能通过验证,validate_on_submit() 返回 True。现在,用户输入的名字可通过字段的 data 属性获取。
在 if 语句中,把名字赋值给局部变量 name,然后再把 data 属性设为空字符串,从而清空表单字段。
最后一行调用 render_template() 函数渲染模板,但这一次参数 name 的值为表单中输入的名字,因此会显示一个针对该用户的欢迎消息。

5. 重定向(Redirects) 和 用户会话(User Session) 

往往使用重定向(redirect)作为post请求的响应,而不是使用常规响应, 即Post/Redirect/Get pattern

from flask import Flask, render_template, session, redirect, url_for

@app.route(‘/‘, methods=[‘GET‘, ‘POST‘])
def index():
    form = NameForm()
    if form.validate_on_submit():
        seesion[‘name‘] = form.name.data
        return redirect(url_for(‘index‘))
    return render_template(‘index.html‘, form=form, name=session.get(‘name‘))

6. Flash消息 

请求完成后,有时需要让用户知道状态发生了变化(可以是确认消息、警告或者错误提醒)
例如,用户提交了有一项错误的登录表单后,服务器发回的响应重新渲染了登录表单,并在表单上面显示一个消息,提示用户用户名或密码错误。

from flask import Flask, render_template, seesion, redirect, url_for, flash

@app.route(‘/‘, method=[‘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 = seesion.get(‘name‘))

仅调用 flash() 函数并不能把消息显示出来,程序使用的模板要渲染这些消息。
Flask 把 get_flashed_messages() 函数开放给模板,用来获取并渲染消息。
get_flashed_messages() 函数获取的消息在下次调用时不会再次返回,因此 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">&times;</button>
        {{ message }}
    </div>
    {% endfor %}
    {% block page_content %}{% endblock %}
</div>
{% endblock %}

在模板中使用循环是因为在之前的请求循环中每次调用 flash() 函数时都会生成一个消息,所以可能有多个消息在排队等待显示。

贴下这节的代码

from flask import Flask, render_template, session, redirect, url_for, flash
from flask.ext.script import Manager
from flask.ext.bootstrap import Bootstrap
from flask.ext.moment import Moment
from flask.ext.wtf import Form
from wtforms import StringField, SubmitField
from wtforms.validators import Required

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

manager = Manager(app)
bootstrap = Bootstrap(app)
moment = Moment(app)

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

@app.errorhandler(404)
def page_not_found(e):
    return render_template(‘404.html‘), 404

@app.errorhandler(500)
def internal_server_error(e):
    return render_template(‘500.html‘), 500

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

if __name__ == ‘__main__‘:
    manager.run()

2015-05-21

时间: 2025-01-02 16:41:52

Flask学习之三——Web表单的相关文章

Flask学习之三 web表单

本部分Miguel Grinberg教程的翻译地址:http://www.pythondoc.com/flask-mega-tutorial/webforms.html 开源中国的:http://www.oschina.net/translate/the-flask-mega-tutorial-part-iii-web-forms 英文原文地址:http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-iii-web-for

flask学习笔记之--表单控件

表单验证 Flask-WTF 从 version 0.9.0有了变化,正确要引用wtforms包 正确的写法: from flask.ext.wtf import Form from wtforms import TextField, BooleanField from wtforms.validators import Required

Flask 里的WEB表单应用

它是HTML页面中负责数据采集的部件.表单有三个部分组成:表单标签.表单域.表单按钮.表单允许用户输入数据,负责HTML页面数据采集,通过表单将用户输入的数据提交给服务器. 创建模板文件 login.html,在其中直接写form表单: <form method="post"> <label>用户名:</label><input type="text" name="username" placeholde

Flask教程 —— Web表单(上)

第二章中介绍的request对象公开了所有客户端发送的请求信息.特别是request.form可以访问POST请求提交的表单数据. 尽管Flask的request对象提供的支持足以处理web表单,但依然有许多任务会变得单调且重复.表单的HTML代码生成和验证提交的表单数据就是两个很好的例子. Flask-WTF扩展使得处理web表单能获得更愉快的体验.该扩展是一个封装了与框架无关的WTForms包的Flask集成. Flask-WTF和它的依赖集可以通过pip来安装: (venv) $ pip

flask笔记:4:web表单

处理web表单表单需要Flask-WTF 在根目录创建一个配置文件 myblog/config.py CSRF_ENABLED=True SECRET_KEY='you-will-never-guess' CSRF_ENABLED配置是为了激活跨站点请求伪造保护 SECRET_KEY是当CSRF激活后,建立一个加密令牌,用于验证表单 修改app/__init__.py from flask import Flask app=Flask(__name__) app.config.from_obje

读书笔记:《HTML5开发手册》Web表单

这是补充HTML5基础知识的第五篇内容,其他为: 一.HTML5-- 新的结构元素 二.HTML5-- figure.time.details.mark 三.HTML5-- details活学活用 四.HTML5-- 现存元素的变化 在之前的笔记中记录了HTML5标签元素的语义以及新定义,本周开始进入Web表单部分的学习,该章节已经读过一遍,很多表单验证的工作都可以通过HTML5完成!现在整理笔记,再次进入Web表单的神奇地域. 因该书出版较早,很多东西已经更改,我会在文中进行更正. 一.表单验

SpringMVC学习系列 之 表单标签

http://www.cnblogs.com/liukemng/p/3754211.html 本篇我们来学习Spring MVC表单标签的使用,借助于Spring MVC提供的表单标签可以让我们在视图上展示WebModel中的数据更加轻松. 一.首先我们先做一个简单了例子来对Spring MVC表单表单标签的使用有一个大致的印象,然后再结合例子对各个标签介绍一下如何使用. 1.首先,在com.demo.web.models包中添加一个模型TagsModel内容如下: package com.de

Symfony2学习笔记之表单

对于一个Web开发者来说,处理HTML表单是一个最为普通又具挑战的任务.Symfony2集成了一个Form组件,让处理表单变的容易起来.在这一节里,我们将从基础开始创建一个复杂的表单,学习表单类库中最重要的内容. Symfony2 的Form组件是一个独立的类库,你可以在Symfony2项目之外使用它. 创建一个简单的表单:假设你要创建一个应用程序的todo列表,需要显示一些任务.因为你的用户需要编辑和创建任务,所以你需要创建一个表单.在你开始之前,首先来看通用的Task类,用来表示和存储一个单

Bootstrap学习笔记(二) 表单

在Bootstrap学习笔记(一) 排版的基础上继续学习Bootstrap的表单,编辑器及head内代码不变. 3-1 基础表单 单中常见的元素主要包括:文本输入框.下拉选择框.单选按钮.复选按钮.文本域和按钮等. 在Bootstrap框架中,通过定制了一个类名`form-control`,也就是说,如果这几个元素使用了类名"form-control",将会实现一些设计上的定制效果. 1.宽度变成了100% 2.设置了一个浅灰色(#ccc)的边框 3.具有4px的圆角 4.设置阴影效果