Web 表单
Flask-WTF
- 安装:
(venv) $ pip install flask-wtf
配置
- 使用app.config对象,它是一个类似字典的对象,可以将配置以键值的方式存储其中。
- (推荐:)配置类存储到单独的Python模块,以保持良好的组织结构。存储在顶级目录下,名为config.py的模块的配置类:
import os
class Config(object):
SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess'
- 优点: 配置设置被定义为Config类中的属性。 一旦应用程序需要更多配置选项,直接依样画葫芦,附加到这个类上即可。
密钥
SECRET_KEY作为加密密钥,用于生成签名或令牌。Flask-WTF插件使用它来保护网页表单免受名为Cross-Site Request
Forgery或CSRF(发音为“seasurf”)的恶意攻击。密钥被定义成由or运算符连接两个项的表达式。第一个项查找环境变量SECRET_KEY的值,第二个项是一个硬编码的字符串。这种首先检查环境变量中是否存在这个配置,找不到的情况下就使用硬编码字符串的配置变量的模式你将会反复看到。在开发阶段,安全性要求较低,因此可以直接使用硬编码字符串。但是,当应用部署到生产服务器上的时候,我将设置一个独一无二且难以揣摩的环境变量,这样,服务器就拥有了一个别人未知的安全密钥了。
- 利用app.config.from_object()方法读配置文件。
from flask import Flask
from config import Config
app = Flask(__name__)
app.config.from_object(Config)
from app import routes
用户登录表单
- 表单类单独存储到名为app/forms.py的模块中,要求用户输入username和password,并提供一个“remember me”的复选框和提交按钮:
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import DataRequired
class LoginForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
remember_me = BooleanField('Remember Me')
submit = SubmitField('Sign In')
# 可选参数validators用于验证输入字段是否符合预期。DataRequired验证器仅验证字段输入是否为空
登录表单模板
- 表单添加到HTML模板以便渲染到网页上,登录模板存储在文件app/templates/login.html 中:
{% extends "base.html" %}
{% block content %}
<h1>Sign In</h1>
<form action="" method="post" novalidate>
{{ form.hidden_tag() }}
<p>
{{ form.username.label }}<br>
{{ form.username(size=32) }}
</p>
<p>
{{ form.password.label }}<br>
{{ form.password(size=32) }}
</p>
<p>{{ form.remember_me() }} {{ form.remember_me.label }}</p>
<p>{{ form.submit() }}</p>
</form>
{% endblock %}
表单视图
视图函数也存储到app/routes.py模块中,只需创建一个form实例,代码如下:
from flask import render_template
from app import app
from app.forms import LoginForm
# ...
@app.route('/login')
def login():
form = LoginForm()
return render_template('login.html', title='Sign In', form=form)
- 基础模板templates/base.html的导航栏上添加登录的链接
<div>
Microblog:
<a href="/index">Home</a>
<a href="/login">Login</a>
</div>
接受表单数据
- Flask-WTF 接受和验证用户提交的数据:
from flask import render_template, flash, redirect
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
flash('Login requested for user {}, remember_me={}'.format(
form.username.data, form.remember_me.data))
return redirect('/index')
return render_template('login.html', title='Sign In', form=form)
完善字段验证
{% extends "base.html" %}
{% block content %}
<h1>Sign In</h1>
<form action="" method="post" novalidate>
{{ form.hidden_tag() }}
<p>
{{ form.username.label }}<br>
{{ form.username(size=32) }}<br>
{% for error in form.username.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.password.label }}<br>
{{ form.password(size=32) }}<br>
{% for error in form.password.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>{{ form.remember_me() }} {{ form.remember_me.label }}</p>
<p>{{ form.submit() }}</p>
</form>
{% endblock %}
生成链接
<div>
Microblog:
<a href="{{ url_for('index') }}">Home</a>
<a href="{{ url_for('login') }}">Login</a>
</div>
from flask import render_template, flash, redirect, url_for
# ...
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
# ...
return redirect(url_for('index'))
# ...