flask web开发笔记 -- 表单 --待整理

虽然Flask的请求对象给表单处理提供了足够的支持,但也有一些任务繁琐和重复。比如为表单生成HTML代码和验证提交表单数据。

Flask-WTF扩展能解决上述问题。它基于wtforms

防止跨站请求伪造

跨站请求伪造(Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。跟跨网站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。中文维基百科参考英文维基百科参考

配置加密的key可以防止CSRF,如下:

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

app.config字典是框架内,扩展或应用程序本身存储配置变量通用的地方,还有方法支持从文件或者环境变量导入。

SECRET_KEY是Flask和一些第三方扩展通用密钥。安全性处决于你的密钥,确认每个应用程序都有不同的安全密钥。更安全起见,密钥要写在环境变量,而不是代码中。

Form类

Flask-WTF中每个表单用继承自Form的类表示,类中定义表单的HTML对象列表。每个HTML对象用对象表示,可以有一个或多个验证。验证是检查用户输入的有效性。

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()])
    submit = SubmitField(‘Submit‘)

WTForms支持的标准HTML对象如下:

Field type Description
StringField Text Field
TextAreaField Multiple-line text Field
PasswordField Password text Field
HiddenField Hidden text Field
DateField Text Field that accepts a datetime.date value in a given format
DateTimeField Text Field that accepts a datetime.datetime value in a given format
IntegerField Text Field that accepts an integer value
DecimalField Text Field that accepts a decimal.Decimal value
FloatField Text Field that accepts a floating-point value
BooleanField Checkbox with True and False values
RadioField List of radio buttons
SelectField Drop-down list of choices
SelectMultipleField Drop-down list of choices with multiple selection
FileField File upload Field
SubmitField Form submission button
FormField Embed a form as a Field in a container form
FieldList List of Fields of a given type

WTForm内置的验证如下:

Validator Description
Email Validates an email address
EqualTo Compares the values of two fields; useful when requesting a password to be entered twice for confirmation
IPAddress Validates an IPv4 network address
Length Validates the length of the string entered
NumberRange Validates that the value entered is within a numeric range
Optional Allows empty input on the field, skipping additional Validators
Required Validates that the field contains data
Regexp Validates the input against a regular expression
URL Validates a URL
AnyOf Validates that the input is one of a list of possible values
NoneOf Validates that the input is none of a list of possible values

表单的HTML渲染

渲染简单的实例:

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

增加属性:

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

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

hello.py修改成如下:

from flask import Flask, render_template
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():
    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)

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

上面指定了方法methods=[‘GET‘, ‘POST‘],如果没有指定,默认使用GET。表单通常用POST来处理。POST时validate_on_submit()调用validate_on_submit()

重定向和用户Session

上例只要一刷新,就会忘记你曾经输入的用户名,为此我们增加session,并使用Post/Redirect/Get模式,修改hello.py:

from flask import Flask, render_template, session, redirect, url_forfrom flask.ext.script import Managerfrom flask.ext.bootstrap import Bootstrapfrom flask.ext.moment import Momentfrom flask.ext.wtf import Formfrom wtforms import StringField, SubmitFieldfrom 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‘), [email protected](500)def internal_server_error(e):
    return render_template(‘500.html‘), [email protected](‘/‘, 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‘))if __name__ == ‘__main__‘:
    manager.run()

动态消息

下面我们在用户名改变的时候增加提示信息。

from flask import Flask, render_template, session, redirect, url_for, flashfrom flask.ext.script import Managerfrom flask.ext.bootstrap import Bootstrapfrom flask.ext.moment import Momentfrom flask.ext.wtf import Formfrom wtforms import StringField, SubmitFieldfrom 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‘), [email protected](500)def internal_server_error(e):
    return render_template(‘500.html‘), [email protected](‘/‘, 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()

templates/base.html修改如下:

{% extends "bootstrap/base.html" %}{% block title %}Flasky{% endblock %}{% block head %}{{ super() }}<link rel="shortcut icon" href="{{ url_for(‘static‘, filename=‘favicon.ico‘) }}" type="image/x-icon"><link rel="icon" href="{{ url_for(‘static‘, filename=‘favicon.ico‘) }}" type="image/x-icon">{% endblock %}{% block navbar %}<div class="navbar navbar-inverse" role="navigation">
    <div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/">Flasky</a>
        </div>
        <div class="navbar-collapse collapse">
            <ul class="nav navbar-nav">
                <li><a href="/">Home</a></li>
            </ul>
        </div>
    </div></div>{% endblock %}{% 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 %}{% block scripts %}{{ super() }}{{ moment.include_moment() }}{% endblock %}

参考资料

    时间: 2025-01-14 09:34:38

    flask web开发笔记 -- 表单 --待整理的相关文章

    flask web开发笔记 -- 快速入门

    flask web开发笔记 -- 快速入门 初始化 Flask应用需要创建应用实例. Web服务器通过Web Server Gateway Interface (WSGI)协议把从客户端接收到的请求传递给该对象.应用程序实例是Flask类对象,通常创建如下: from flask import Flask app = Flask(__name__) Flask类的构造函数唯一的参数是应用的主模块名或包名,用于确定应用的根目录.对于大多数应用程序,使用Python的__name__变量即可. 路由

    flask web开发笔记 -- 数据库

    关系数据库基于关系,有主键.外键等.它存储数据高效,避免了重复:修改数据方便.缺点是连接的成本过高. NoSQL尽量避免连接,但是增加了数据冗余,修改数据麻烦,不过查询快速. 对于中小型的应用,两者的效率差别不大. python数据库框架 Flask对数据库没有限制,你可以使用MySQL, Postgres, SQLite, Redis, MongoDB或CouchDB等.另外还有数据抽象层SQLAlchemy和MongoEngine等. 选择数据库时需要关注: 易用性:抽象层,比如ORM(ob

    flask web开发笔记 -- 简介

    Flask是使用Python编写的轻量级Web应用框架.它基于Werkzeug WSGI工具包和Jinja2 模板引擎. Flask使用BSD授权. Flask基于Python的灵活,为Web开发提供简单的模板.demo:Flask community Flask也被称为微框架,因为它核心简单但扩展性好.Flask没有数据库层.表单验证等第三方已经存在的通用功能.Flask的扩展可以像flask自己实现一样使用这些功能.扩展有ORM(object-relational mappers,对象关系映

    flask web开发笔记 -- 模板

    业务(business logic 比如插入数据库)和展示逻辑(presentation logic, 比如生成返回)最好分开,展示逻辑可以放置在模板中.模板是一个包含响应文本的文件,用占位符变量表示动态部分.rendering(渲染):把占位符用实际值代替,并返回最终响应字符串.Flask采用模板引擎Jinja2. 模板引擎Jinja2 简单的模板:templates/index.html <h1>Hello World!</h1> 带参数的模板:templates/user.h

    .net web 开发平台- 表单设计器 一(web版)

    如今为了适应需求的不断变化,动态表单设计器应运而生.它主要是为了满足界面的不断变化和提高开发速度.比如:一些页面客户可能也无法确定页面的终于布局,控件的位置,在哪种情况下显示或不显示等可能须要随时改动.为了应对这些需求而不去多次改动源码进行公布,就能够在项目中使用动态表单设计器.如今分享一下我做的动态表单设计器的设计思路,共同学习. 想做一个表单设计器,首先要确定是做c/s的还是b/s.我考虑到以后的发展方向是c/s向b/s转化,所以就选择了b/s的方向,并且做b/s比做c/s要简单非常多.在做

    Flask之旅《Flask Web开发:基于Python的Web应用开发实战》学习笔记

    <Flask Web开发:基于Python的Web应用开发实战> 点击上方的"目录"快速到达哦! 虽然简单的网站(Flask+Python+SAE)已经上线,但只是入门.开发大型网站,系统地学习一遍还是有必要的. 1 虚拟环境 2016-6-8 书上介绍了 virtualenv,每个venv都会拷贝一份packages到项目 /venv目录. virtualenv venv venv\Scripts\activate.bat (venv) $ pip freeze >

    jQuery几个经典表单应用整理回顾

    1.文本框获得(失去)焦点 当文本框获得输入焦点时,将该文本框高亮显示,算不得一个应用,只是一个小技巧,可以提高用户体验. [html] view plaincopy <span style="font-family:SimSun;font-size:12px;"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xht

    移动web开发笔记

    移动web开发笔记 移动web开发笔记 基础概念 像素单位 CSS pixels与device pixels CSS pixels PPIDPI devicePiexelRatio 文字大小控制 viewport 响应式布局 原则 实现方式 布局方案 百分比布局流体布局 弹性flexible布局 flex-box布局 图片处理 普通设置 响应式图片 媒体查询 HTML5 新表单类型 HTML5的新输入类型 CSS3 设备控制 设备交互 性能优化 参考: 移动web开发入门 移动端web开发技巧

    《Flask Web开发——基于Python的Web应用开发实践》一字一句上机实践(下)

    目录 前言 第8章 用户认证 第9章 用户角色 第10章 用户资料 第11章 博客文章 第12章 关注者 第13章 用户评论 第14章 应用编程接口   前言 第1章-第7章学习实践记录请参见:<Flask Web开发——基于Python的Web应用开发实践>一字一句上机实践(上) 本文记录自己学习<Flask Web开发——基于Python的Web应用开发实践>的第8章-第14章内容.相比于刚开始学习第1-7章内容来说,本部分内容实战性更强,而且在书本上遇到的问题也相对较少,如果