4.1 跨站请求伪造保护
为了实现 CSRF 保护,Flask-WTF 需要程序设置一个密钥。Flask-WTF 使用这个密钥生成加密令牌,再用令牌验证请求中表单数据的真伪。
设置Flask-WTF
app = Flask(name)
app.config[‘SECRET_KEY’] = ‘hard to guess string’
app.config 字典可用来存储框架、扩展和程序本身的配置变量。使用标准的字典句法就能把配置值添加到 app.config 对象中。这个对象还提供了一些方法,可以从文件或环境中导入配置值。
SECRET_KEY 配置变量是通用密钥,可在 Flask 和多个第三方扩展中使用。如其名所示,加密的强度取决于变量值的机密程度。不同的程序要使用不同的密钥,而且要保证其他人不知道你所用的字符串
4.2 表单类
狗书上有的不赘述,聊聊表单样式的自定义
在模板里我们可以手写表单,也可以用Flask-Bootstrap
#使用 Flask-Bootstrap中预先定义好的表单样式渲染整个 Flask-WTF 表单
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}知乎 - 与世界分享你刚编的故事{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>知乎</h1>
</div>
<div class="col-md-4">
{{ wtf.quick_form(form) }}
<br>
<p>无法登录?<a href="">重置密码</a>.</p>
<p>还没有账号? <a href="{{url_for('auth.register')}}">注册账号</a>.</p>
</div>
{% endblock %}
#导入的 bootstrap/wtf.html 文件中定义了一个使用 Bootstrap 渲染 Falsk-WTF 表单对象的辅助函数。 wtf.quick_form() 函数的参数为 Flask-WTF 表单对象,使用 Bootstrap 的默认样式渲染传入的表单
那我们想自定义样式,不想用默认样式的话怎么办?
第一种方法:可以在forms.py里面定义表单类的时候定义样式
from flask_wtf import Form
from wtforms import StringField,PasswordField,BooleanField,SubmitField
from wtforms.validators import Required,Length,Email,EqualTo
from wtforms import ValidationError
from ..models import User
#继承Flask-WTF 的Form类来编写表单,电子邮件字段用到了 WTForms 提供的 Length() 和 Email() 验证函数。 PasswordField 类表示属性为 type="password" 的 <input> 元素。 BooleanField 类表示复选框。
#登录页面使用的模板保存在 auth/login.html 文件中。这个模板只需使用 Flask-Bootstrap 提供的 wtf.quick_form() 宏渲染表单即可
class LoginForm(Form):
#可以在表单类里传入一个字典(render_kw),把需要添加到字段的属性以键值对的形式写进去,前端就能渲染出来
email = StringField(u'邮箱账号', validators=[Required(u'邮箱不能为空!'),Length(1,64),Email()],render_kw={'aria-label':u'邮箱', 'placeholder': u'邮箱'})
password = PasswordField('密码',validators=[Required()],render_kw={'aria-label':u'密码', 'placeholder': u'密码(不少于 6 位)','type':'password','autocomplete':'off'})
remember_me = BooleanField('下次自动登录')
submit = SubmitField(u'登录')
class RegisteationForm(Form):
email = StringField('邮箱', validators=[Required(),Length(1,64),Email()],render_kw={'aria-label':u'邮箱', 'placeholder': u'邮箱'})
username = StringField('用户名',validators=[Required(),Length(1.64)],render_kw={'aria-label':u'昵称', 'placeholder': u'昵称'})
password = PasswordField('密码',validators=[Required(),EqualTo('password2', message='两次输入的密码必须一致')],render_kw={'aria-label':u'密码', 'placeholder': u'密码(不少于 6 位)','type':'password','autocomplete':'off'})
password2 = PasswordField('确认密码',validators=[Required()],render_kw={'aria-label':u'确认密码', 'placeholder': u'确认密码(不少于 6 位)','type':'password','autocomplete':'off'})
submit = SubmitField(u'确认注册')
def validate_email(self,field):
if User.query.filter_by(email=field.data).first():
raise ValidationError('此邮箱已经被注册过了')
def validate_username(self,field):
if User.query.filter_by(username=field.data).first():
raise ValidationError('此昵称已经被注册过了')
上面这段代码我们在定义表单类的时候传入了一个字典 render_kw,把需要的属性用键值对的方法写进去即可
前端模版这么写:
<form role="form" action="{{ url_for('auth.login') }}" method="POST">
{{ form.hidden_tag() }}
<div class="group-inputs">
<div class="name input-wrapper">
{{ form.email() }}
</div>
<div class="input-wrapper">
{{ form.password() }}
</div>
</div>
<div class="button-wrapper command">
{{ form.submit(class="sign-button submit") }}
</div>
</form>
第二种方法:在渲染时控制样式
这种方法无须多说,狗书上也写了
例通过参数 form 传入模板,在模板中可以生成一个简单的表单,如下所示:
<form method="POST">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name() }}
{{ form.submit() }}
</form>
当然,这个表单还很简陋。要想改进表单的外观,可以把参数传入渲染字段的函数,传入
的参数会被转换成字段的 HTML 属性。例如,可以为字段指定 id 或 class 属性,然后定
义 CSS 样式:
<form method="POST">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name(id='my-text-field') }}
{{ form.submit() }}
</form>