码迷,mamicode.com
首页 > Web开发 > 详细

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

时间:2015-06-08 11:49:07      阅读:360      评论:0      收藏:0      [点我收藏+]

标签:


虽然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‘), 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():
        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‘), 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()

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


参考资料



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

标签:

原文地址:http://my.oschina.net/u/1433482/blog/464054

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!