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">×</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
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。