Django 当中有form类,这个类给开发者提供了相当丰富的校验方式。
Flask和django同样推出了form类的插件,flask-wtf
一、flask form表单的安装和简单字段属性的应用
1、安装flask form插件
pip install flask-wtf
2、flask项目主目录下创建forms.py文件
3、表单常用的字段
字段 | 说明 |
---|---|
StringField | 字符串 |
IntegerField | 整型 |
TextAreaField | 文本 |
PasswordField | 密码 |
HiddenField | 隐藏域 |
DateField | Datatime.data格式 年月日 |
DateTimeField | Datatime.datatime 格式 年月日 时分秒 |
FloatField | 小数 |
RadioField | 单选 |
SelectField | 下拉 |
FileField | 文件 |
SubmitField | 提交 |
表单常用的校验
校验参数 | 说明 |
---|---|
邮件校验 | |
EqualTo | 比较两个字段的值,常用于密码比较 |
IPAddress | Ipv4格式的IP地址 |
Length | 长度 |
NumberRange | 数字范围 |
DataRequired | 空值检查 |
Url | 验证是否符合url格式 |
AnyOf | 确保输入值在指定范围 |
NoneOf | 确保输入的值不在范围 |
4、在forms.py文件中导入form表单相关模块,并定义一个Form类
import wtforms # 定义字段
from flask_wtf import FlaskForm # 定义表单
from wtforms import validators # 定义校验
from FlaskStudent.models import Course
course_list = [(c.id,c.name) for c in Course.query.all()]
class TeacherForm(FlaskForm):
"""
form字段的参数
label=None, 表单的标签
validators=None, 校验,传入校验的方法
filters=tuple(), 过滤
description='', 描述
id=None, html id
default=None, 默认值
widget=None, HTML样式
render_kw=None, HTML属性 参数
"""
name = wtforms.StringField(
label="教师姓名",
render_kw={
"class": "form-control",
"placeholder": "教师姓名"
},
validators=[
validators.DataRequired("姓名不可以为空")
]
)
age = wtforms.IntegerField(
label="教师年龄",
render_kw={
"class": "form-control",
"placeholder": "教师年龄"
},
validators=[
validators.DataRequired("年龄不可以为空")
]
)
gender = wtforms.SelectField(
label="教师性别",
render_kw={
"class": "form-control",
},
choices=[
("1","男"),
("2","女")
]
)
course = wtforms.SelectField(
label="学科",
render_kw={
"class": "form-control",
},
choices=course_list
)
submit = wtforms.SubmitField(
label="提交",
render_kw={
"class": "btn btn-primary btn-block",
},
)
5、视图路由文件中定义一个视图函数,并实例化表单,用于前端渲染
@app.route("/add_teacher/",methods=["GET","POST"])
def add_teacher():
teacher_form = TeacherForm()
return render_template("add_teacher.html",**locals())
6、前端页面,使用变量渲染form类中的字段
7、页面效果
二、flask form 中csrf_token 的使用
flask-wtf模块是携带csrf校验的,只是需要开启。在flask form中默认csrf_token 是没有开启的,需要我们手动去启动form表单的csrf_token。
csrf是针对于post请求的跨域限制,对get请求是没有作用的。
1、首先更改form表单的请求方式为post
2、首先在项目起始位置开启CSRFProtect,也就是main.py
这里注意由于版本问题,现在可以使用csrfProtect,之前版本会更新到CSRFProtect,所以我们现在索性就直接使用CSRFProtect,避免之后出现问题
导入CSRFProtect模块,关联flask应用
import pymysql
from flask import Flask
from flask import session
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import CSRFProtect # 导入csrf校验模块,csrfProtect在1.0之后移除
pymysql.install_as_MySQLdb()
app = Flask(__name__)
# 关联csrf和flask应用
csrf = CSRFProtect(app)
# 使用类配置加载
app.config.from_object('config.DebugConfig')
# 关联sqlalchemy和flask应用
db = SQLAlchemy(app)
3、然后在前端使用csrf_token就可以了
这里是根据form表单实例去使用csrf_token的
如果不配置这句话,而程序入口已经开启了应用的CSRF校验,则会在表单提交时报错
4、前端页面上打开开发者调试模式,查看csrf_token是否已经生成在隐藏域中
这里注意:
Django中的csrf_token的name名为middlewarecsrftoken
Flask中的csrf_token的name名为csrf_token
三、临时关闭csrf校验
有时候我们有一些功能虽然用的是post请求,但是又不想进行csrf校验,同时其他的一些功能视图还是需要用csrf校验的,这个时候就需要用到csrf内置的功能,临时关闭保护。
针对于指定的单个视图取消csrf的保护
在不需要保护的路由上方加上这句话:
@csrf.exempt
前提是开启CSRF时需要将CSRFProtect使用一个csrf变量实例化
然后在视图中导入main.py中应用的csrf对象
最后在不需要保护的视图路由上方加上这句话
这个时候哪怕是程序入口开启了csrf,还有前端页面页使用了表单实例的csrf_token,但是这时候是不会进行csrf的校验的
from flask import request
from flask import redirect
from flask import render_template
from FlaskStudent.main import app
from FlaskStudent.models import *
from FlaskStudent.main import csrf
from FlaskStudent.main import session
from FlaskStudent.forms import TeacherForm
@csrf.exempt # 临时关闭csrf校验
@app.route("/add_teacher/",methods=["GET","POST"])
def add_teacher():
teacher_form = TeacherForm()
return render_template("add_teacher.html",**locals())
四、定义csrf错误页面
就是在form表单提交,csrf校验失败(不通过)的情况下,不进行下面的报错
而是跳转到指定的错误提示页面。
这里我们需要新建一个错误提示页面:命名为csrf_403.html
{% extends "blank.html" %}
{% block label %}
403 error
{% endblock %}
{% block container %}
<div class="text-center">
<div class="error mx-auto" data-text="403">403</div>
<p class="lead text-gray-800 mb-5">csrf_token error</p>
<p class="text-gray-500 mb-0">please check your settings or form,csrf_token is missing ! </p>
</div>
{% endblock %}
再定义一个csrf_403的路由视图,用于发生校验错误跳转
这里必须传递一个参数reason,也不需要使用它或是返回它。如果不传递,csrf内置代码就识别不了,会报错。
# csrf 如果没有配置跳转的错误页面
# @csrf.error_handler
@app.route("/csrf_403/")
def csrf_tonken_error(reason):
return render_template("csrf_403.html")
视图路由定义完了,再跟关闭csrf保护一样,在路由上方添加一个装饰器
@csrf.error_handler
添加这句话之后,只要前端提交表单时csrf校验失败,就是跳转到该路由视图指定的页面(该方法使用于所有csrf校验失败的视图)
from flask import request
from flask import redirect
from flask import render_template
from FlaskStudent.main import app
from FlaskStudent.models import *
from FlaskStudent.main import csrf
from FlaskStudent.main import session
from FlaskStudent.forms import TeacherForm
@csrf.exempt # 临时关闭csrf校验
@app.route("/add_teacher/",methods=["GET","POST"])
def add_teacher():
teacher_form = TeacherForm()
return render_template("add_teacher.html",**locals())
# csrf 如果没有配置跳转的错误页面
@csrf.error_handler # csrf错误跳转
@app.route("/csrf_403/")
def csrf_tonken_error(reason):
return render_template("csrf_403.html")
效果:
我现在将add_teacher.html页面上的csrf变量注释掉
这个时候提交表单
就会跳转的定义的403页面