第四章
4.2使用Flask—WTF处理表单
-
默认为每个表单启用CSRF保护,为我们自动生成和验证CSRF令牌
-
默认使用程序秘钥对CSRF令牌签名,设置秘钥:app.secret_key = os.getenv('SECRET_KEY', 'secret string')
4.2.1定义表单类
-
使用WTForms创建表单时,类要继承从WTForms导入的Form基类
-
字段属性通过实例化WTForms提供的字段类表示,名称作为对应HTML<input>元素的name属性和id属性。注意:名称大小写敏感,不能以下划线或validate开头
-
实例化字段类的参数有:
-
label:字段标签<label>的值,也就是渲染后再输入字段前的提示文字
-
render_kw:字典类型,设置<input>标签的属性,如{‘'placeholder':'haha'}
-
validators:列表,包含一系列验证器。验证器是用于验证字段数据的类,从wtforms.validators模块导入。实例化验证类时,message参数传入自定义错误信息
-
default:字符串或可调用对象,给字段设置默认值
-
-
-
使用Flask—WTF创建表单,要继承FlaskForm类,其他操作与上条一样
4.2.2输出HTML代码
-
输出字段的HTML代码,用’form.字段名‘。如:form.username
-
输出字段<label>的代买,用"form.字段名.label".如:form.username.label
-
给字段增加属性
-
使用render_kw属性
-
在调用时加括号使用关键字参数的形式传入。如:form.username(style='width:20px;',class='bar')
-
4.2.3模板渲染表单
-
调用表单类的字段属性即可,同时也可以添加括号增加字段属性
{{form.username}} / {{form.username(class='bar')}}
-
Flask-WTF自动验证CSRF令牌,所以为了通过验证,需手动渲染这个字段。{{form.csrf_token}}
4.3.2验证表单数据
-
单纯使用WTForms,实例化表单类时要把request.form出入表单类,而Flask-WTF,不需要手动传入。注意:POST提交的表单,通过request.form获取数据,而GET提交的表单,通过request.args获取数据
-
验证表单
-
首先实例化表单,再调用validate()方法验证表单。若对GET和POST请求执行不同代码,如GET渲染模板,POST调用validate()方法验证数据。即if reques.method =='POST' and form.validate():
-
form.validate_on_submit()合并了上面两个操作,但除了POST方法,PUT、PATCH、DELETE也会验证表单数据
-
form.data是匹配所有字段与对应数据的字典,一般使用form.字段属性名.data获取对应字段的数据列表
-
对表单的请求使用PRG(Post/Redirect/Get)模式,即:对请求表单的POST请求返回重定向响应将最后一个请求转换为GET请求
-
4.3.3模板渲染错误消息
-
form.errors匹配所有字段与对应错误消息的字典,一般使用form.字段属性名.errors获取对应字段的错误消息列表
-
像渲染flash()消息一样,可以使用for循环迭代错误消息列表
-
疑问:验证失败将错误消息添加到表单类实例的errors属性是自动进行的吗?不需手动传递?
4.4.2使用宏渲染表单
-
模板渲染需要重复做的工作:
-
调用字段属性,获取<input>定义
-
调用对应的label属性,获取<label>定义
-
渲染错误消息
-
-
macro.html的内容:
{% macro form_field(field) %}
{{ field.label }}<br>
{{ field(**kwargs) }}<br>
{% if field.errors %}
{% for error in field.errors%}
...
{% endfor%}
{% endif %}
{% endmacro %}
-
模板文件渲染的内容:
{% from 'macro.html' import form_field %}
<form method='POST'>
{{ form.csrf_token }}
{{ form_field(form.username) }}
form>
4.4.3自定义验证器
-
行内验证器
-
在表单类中定义以“validate_字段属性名”形式命名的方法,该方法接收两个位置参数,依次是form和field,前者是表单实例,后者是字段对象,field.data获取字段数据,这两个位置参数在验证表单时被调用传入。验证出错抛出ValidationError异常,传入错误信息做参数,如raise ValidationError('错了信息')
-
-
全局验证器
-
实现工厂函数,即返回一个可调用的函数
-
4.4.4文件上传
-
app.config['MAX_CONTENT_LENGTH']=1024*3 注意:默认单位为字节。app.config['UPLOAD_PATH']配置上传文件的目的文件夹
-
文件上传表单,需将表单的enctype属性设为“multipart/form-data”
-
手动处理时,request.files.get('photo')获取。当使用Flask—WTF时,会自动帮我们获取对应的文件对象,仍使用表单类属性的data属性获取,如:form.字段名.data
-
使用文件对象的save(‘文件保存路径'')方法保存文件。如:
f=form.photo.data
f.save('/uploads/photo.jpg')
-
send_from_directory(),通过传入的文件路径返回相应的文件内容,类似Flask内置的static视图
-
多文件上传时,使用request.files。getlist('photo')获取所有上传文件对象的列表
4.4.6单表单多提交按钮
-
只有被单击的提交字段才会解析到request.form字典中。一般使用form.字段名.data,被单击的值是True,未被单击则是False
4.4.7单页面多表单
-
单视图处理
-
一个页面多个表单时,要判断是哪个表单被提交。Flask-WTF根据请求方法判断表单是否提交,不判断是哪个表单被提交,需要手动判断。
-
可以给两个表单的提交字段设置不同的name属性,使用form.字段名.data判断是否被提交
-
-
多视图处理
-
使用不同视图函数对表单进行处理,两表单的提交字段的name可以使用相同名称,在视图函数中可继续form.validate_on_submit()方法验证
-
疑问:
-