Tyrion是一个基于Python实现的支持多个WEB框架的Form表单验证组件,其完美的支持Tornado、Django、Flask、Bottle Web框架。Tyrion主要有两大重要动能:
- 表单验证
- 生成HTML标签
- 保留上次提交内容
对于表单验证,告别书写重复的正则表达式对用户提交的数据进行验证的工作,从此解放双手,跟着我左手右手一个慢动作…
对于生成HTML标签,不在人工书写html标签,让Tyrion帮你自动创建…
对于保留上次提交内容,由于默认表单提交后页面刷新,原来输入的内容会清空,Tyrion可以保留上次提交内容。
github:https://github.com/WuPeiqi/Tyrion
使用文档
1、下载安装
1 pip install PyTyrion
github: https://github.com/WuPeiqi/Tyrion
2、配置WEB框架种类
由于Tyrion同时支持Tornado、Django、Flask、Bottle多个WEB框架,所有在使用前需要进行指定。
1 import Tyrion 2 Tyrion.setup('tornado') 3 # setup的参数有:tornado(默认)、django、bottle、flask
Form类用于提供验证规则、插件属性、错误信息等
1 from Tyrion.Forms import Form 2 from Tyrion.Fields import StringField 3 from Tyrion.Fields import EmailField 4 5 class LoginForm(Form): 6 username = StringField(error={'required': '用户名不能为空'}) 7 password = StringField(error={'required': '密码不能为空'}) 8 email = EmailField(error={'required': '邮箱不能为空', 'invalid': '邮箱格式错误'})
4、验证用户请求
前端HTML代码:
1 <form method="POST" action="/login.html"> 2 <div> 3 <input type="text" name="username"> 4 </div> 5 <div> 6 <input type="text" name="password"> 7 </div> 8 <div> 9 <input type="text" name="email"> 10 </div> 11 12 <input type="submit" value="提交"> 13 </form>
用户提交数据时,在后台书写如下代码即可实现用户请求数据验证(Tornado示例):
1 class LoginHandler(tornado.web.RequestHandler): 2 def get(self, *args, **kwargs): 3 self.render('login.html') 4 5 def post(self, *args, **kwargs): 6 form = LoginForm(self) 7 8 ###### 检查用户输入是否合法 ###### 9 if form.is_valid(): 10 11 ###### 如果不合法,则输出错误信息 ###### 12 print(form.error_dict) 13 else: 14 ###### 如果合法,则输出用户输入的内容 ###### 15 print(form.value_dict) 16 self.render('login.html')
示例01:源码下载(含Tornado、Django、Flask、Bottle)
5、验证用户请求 && 生成HTML标签 && 保留上次输入内容 && 错误提示
Tyrion不仅可以验证用户请求,还可以生成自动创建HTML标签并且可以保留用户上次输入的内容。在HTML模板中调用Form类对象的字段即可,如(Tornado示例):
from Tyrion.Forms import Form from Tyrion.Fields import StringField from Tyrion.Fields import EmailField class LoginForm(Form): username = StringField(error={'required': '用户名不能为空'}) password = StringField(error={'required': '密码不能为空'}) email = EmailField(error={'required': '邮箱不能为空', 'invalid': '邮箱格式错误'})
1 class LoginHandler(tornado.web.RequestHandler): 2 def get(self, *args, **kwargs): 3 form = LoginForm(self) 4 self.render('login.html', form=form) 5 6 def post(self, *args, **kwargs): 7 form = LoginForm(self) 8 9 print(form.is_valid()) 10 print(form.error_dict) 11 print(form.value_dict) 12 13 self.render('login.html', form=form)
1 <form method="post" action="/login.html"> 2 <div> 3 <!-- Form创建的标签 --> 4 {% raw form.username %} 5 6 <!-- 错误信息 --> 7 <span>{{form.error_dict.get('username',"")}}</span> 8 </div> 9 <div> 10 {% raw form.password %} 11 <span>{{form.error_dict.get('password',"")}}</span> 12 </div> 13 <div> 14 {% raw form.email %} 15 <span>{{form.error_dict.get('email',"")}}</span> 16 </div> 17 <input type="submit" value="提交"/
注意: HTML模板中的转义
示例02:源码下载(含有Tornado、Django、Flask、Bottle)
6、Form字段类型
Form的字段用于指定从请求中获取的数据类型以及格式,以此来验证用户输入的内容。
1 from Tyrion.Forms import Form 2 from Tyrion.Fields import StringField 3 from Tyrion.Fields import EmailField 4 5 class LoginForm(Form): 6 username = StringField(error={'required': '用户名不能为空'}) 7 password = StringField(error={'required': '密码不能为空'}) 8 email = EmailField(error={'required': '邮箱不能为空', 'invalid': '邮箱格式错误'})
以上代码表示此Form类可以用于验证用户输入的内容,并且 username和password必须不能为空,email必须不能为空并且必须是邮箱格式。
目前支持所有字段:
1 StringField 2 """ 3 要求必须是字符串,即:正则^.*$ 4 5 参数: 6 required 布尔值,是否允许为空 7 max_length 整数,限制用户输入内容最大长度 8 min_length 整数,限制用户输入内容最小长度 9 error 字典,自定义错误提示,如:{ 10 'required': '值为空时的错误提示', 11 'invalid': '格式错误时的错误提示', 12 'max_length': '最大长度为10', 13 'min_length': '最小长度为1', 14 } 15 widget 定制生成的HTML插件(默认InputText) 16 """ 17 18 EmailField 19 """ 20 要求必须是邮箱格式的字符串 21 22 参数: 23 required 布尔值,是否允许为空 24 max_length 整数,限制用户输入内容最大长度 25 min_length 整数,限制用户输入内容最小长度 26 error 字典,自定义错误提示,如:{ 27 'required': '值为空时的错误提示', 28 'invalid': '格式错误时的错误提示', 29 'max_length': '最大长度为10', 30 'min_length': '最小长度为1', 31 } 32 widget 定制生成的HTML插件(默认InputText) 33 """ 34 35 IPField 36 """ 37 要求必须是IP格式 38 39 参数: 40 required 布尔值,是否允许为空 41 max_length 整数,限制用户输入内容最大长度 42 min_length 整数,限制用户输入内容最小长度 43 error 字典,自定义错误提示,如:{ 44 'required': '值为空时的错误提示', 45 'invalid': '格式错误时的错误提示', 46 'max_length': '最大长度为10', 47 'min_length': '最小长度为1', 48 } 49 widget 定制生成的HTML插件(默认InputText) 50 51 """ 52 53 IntegerField 54 """ 55 要求必须整数格式 56 57 参数: 58 required 布尔值,是否允许为空 59 max_value 整数,限制用户输入数字最大值 60 min_value 整数,限制用户输入数字最小值 61 error 字典,自定义错误提示,如:{ 62 'required': '值为空时的错误提示', 63 'invalid': '格式错误时的错误提示', 64 'max_value': '最大值为10', 65 'max_value': '最小值度为1', 66 } 67 widget 定制生成的HTML插件(默认InputText) 68 69 """ 70 71 FloatField 72 """ 73 要求必须小数格式 74 75 参数: 76 required 布尔值,是否允许为空 77 max_value 整数,限制用户输入数字最大值 78 min_value 整数,限制用户输入数字最小值 79 error 字典,自定义错误提示,如:{ 80 'required': '值为空时的错误提示', 81 'invalid': '格式错误时的错误提示', 82 'max_value': '最大值为10', 83 'max_value': '最小值度为1', 84 } 85 widget 定制生成的HTML插件(默认InputText) 86 """ 87 88 StringListField 89 """ 90 用于获取请求中的多个值,且保证每一个元素是字符串,即:正则^.*$ 91 如:checkbox或selct多选时,会提交多个值,用此字段可以将用户提交的值保存至列表 92 93 参数: 94 required 布尔值,是否允许为空 95 ele_max_length 整数,限制用户输入的每个元素内容最大长度 96 ele_min_length 整数,限制用户输入的每个元素内容最小长度 97 error 字典,自定义错误提示,如:{ 98 'required': '值为空时的错误提示', 99 'element': '列表中的元素必须是字符串', 100 'ele_max_length': '最大长度为10', 101 'ele_min_length': '最小长度为1', 102 } 103 widget 定制生成的HTML插件(默认InputMultiCheckBox,即:checkbox) 104 """ 105 106 IntegerListField 107 """ 108 用于获取请求中的多个值,且保证每一个元素是整数 109 如:checkbox或selct多选时,会提交多个值,用此字段可以将用户提交的值保存至列表 110 111 参数: 112 required 布尔值,是否允许为空 113 ele_max_value 整数,限制用户输入的每个元素内容最大长度 114 ele_min_value 整数,限制用户输入的每个元素内容最小长度 115 error 字典,自定义错误提示,如:{ 116 'required': '值为空时的错误提示', 117 'element': '列表中的元素必须是数字', 118 'ele_max_value': '最大值为x', 119 'ele_min_value': '最小值为x', 120 } 121 widget 定制生成的HTML插件(默认InputMultiCheckBox,即:checkbox) 122 """
7、Form字段widget参数:HTML插件
HTML插件用于指定当前字段在生成HTML时表现的种类和属性,通过指定此参数从而实现定制页面上生成的HTML标签
1 from Tyrion.Forms import Form 2 from Tyrion.Fields import StringField 3 from Tyrion.Fields import EmailField 4 5 from Tyrion.Widget import InputPassword 6 7 class LoginForm(Form): 8 password = StringField(error={'required': '密码不能为空'},widget=InputPassword())
上述LoginForm的password字段要求用户输入必须是字符串类型,并且指定生成HTML标签时会创建为<input type=’password’ > 标签
目前支持所有插件:
1 InputText 2 """ 3 设置Form对应字段在HTML中生成input type='text' 标签 4 5 参数: 6 attr 字典,指定生成标签的属性,如: attr = {'class': 'c1', 'placeholder': 'username'} 7 """ 8 InputEmail 9 """ 10 设置Form对应字段在HTML中生成input type='email' 标签 11 12 参数: 13 attr 字典,指定生成标签的属性,如: attr = {'class': 'c1', 'placeholder': 'username'} 14 """ 15 InputPassword 16 """ 17 设置Form对应字段在HTML中生成input type='password' 标签 18 19 参数: 20 attr 字典,指定生成标签的属性,如: attr = {'class': 'c1', 'placeholder': 'username'} 21 """ 22 TextArea 23 """ 24 设置Form对应字段在HTML中生成 textarea 标签 25 26 参数: 27 attr 字典,指定生成标签的属性,如: attr = {'class': 'c1'} 28 value 字符串,用于设置textarea标签中默认显示的内容 29 """ 30 31 InputRadio 32 """ 33 设置Form对应字段在HTML中生成一系列 input type='radio' 标签(选择时互斥) 34 35 参数: 36 attr 字典,生成的HTML属性,如:{'class': 'c1'} 37 text_value_list 列表,生成的多个radio标签的内容和值,如:[ 38 {'value':1, 'text': '男'}, 39 {'value':2, 'text': '女'}, 40 ] 41 checked_value 整数或字符串,默认被选中的标签的value的值 42 43 示例: 44 from Tyrion.Forms import Form 45 from Tyrion.Fields import IntegerField 46 47 from Tyrion.Widget import InputRadio 48 49 50 class LoginForm(Form): 51 favor = IntegerField(error={'required': '爱好不能为空'}, 52 widget=InputRadio(attr={'class': 'c1'}, 53 text_value_list=[ 54 {'value': 1, 'text': '男'}, 55 {'value': 2, 'text': '女'}, ], 56 checked_value=2 57 ) 58 ) 59 上述favor字段生成的HTML标签为: 60 <div> 61 <span> 62 <input class='c1' type="radio" name="gender" value="1"> 63 </span> 64 <span>男</span> 65 </div> 66 <div> 67 <span> 68 <input class='c1' type="radio" name="gender" value="2" checked='checked'> 69 </span> 70 <span>女</span> 71 </div> 72 """ 73 74 InputSingleCheckBox 75 """ 76 设置Form对应字段在HTML中生成 input type='checkbox' 标签 77 参数: 78 attr 字典,指定生成标签的属性,如: attr = {'class': 'c1'} 79 """ 80 81 InputMultiCheckBox 82 """ 83 设置Form对应字段在HTML中生成一系列 input type='checkbox' 标签 84 85 参数: 86 attr 字典,指定生成标签的属性,如: attr = {'class': 'c1'} 87 text_value_list 列表,生成的多个checkbox标签的内容和值,如:[ 88 {'value':1, 'text': '篮球'}, 89 {'value':2, 'text': '足球'}, 90 {'value':3, 'text': '乒乓球'}, 91 {'value':4, 'text': '羽毛球'}, 92 ] 93 checked_value_list 列表,默认选中的标签对应的value, 如:[1,3] 94 """ 95 SingleSelect 96 """ 97 设置Form对应字段在HTML中生成 单选select 标签 98 99 参数: 100 attr 字典,指定生成标签的属性,如: attr = {'class': 'c1'} 101 text_value_list 列表,用于指定select标签中的option,如:[ 102 {'value':1, 'text': '北京'}, 103 {'value':2, 'text': '上海'}, 104 {'value':3, 'text': '广州'}, 105 {'value':4, 'text': '重庆'}, 106 ] 107 selected_value 数字或字符串,默认被选中选项对应的值,如: 3 108 """ 109 110 MultiSelect 111 """ 112 设置Form对应字段在HTML中生成 多选select 标签 113 114 参数: 115 attr 字典,指定生成标签的属性,如: attr = {'class': 'c1'} 116 text_value_list 列表,用于指定select标签中的option,如:[ 117 {'value':1, 'text': '篮球'}, 118 {'value':2, 'text': '足球'}, 119 {'value':3, 'text': '乒乓球'}, 120 {'value':4, 'text': '羽毛球'}, 121 ] 122 selected_value_list 列表,默认被选中选项对应的值,如:[2,3,4] 123 """
8、动态初始化默认值
由于Form可以用于生成HTML标签,如果想要在创建标签的同时再为其设置默认值有两种方式:
- 静态,在插件参数中指定
- 动态,调用Form对象的 init_field_value 方法来指定
1 class InitValueForm(Form): 2 username = StringField(error={'required': '用户名不能为空'}) 3 age = IntegerField(max_value=500, 4 min_value=0, 5 error={'required': '年龄不能为空', 6 'invalid': '年龄必须为数字', 7 'min_value': '年龄不能小于0', 8 'max_value': '年龄不能大于500'}) 9 10 city = IntegerField(error={'required': '年龄不能为空', 'invalid': '年龄必须为数字'}, 11 widget=SingleSelect(text_value_list=[{'value': 1, 'text': '上海'}, 12 {'value': 2, 'text': '北京'}, 13 {'value': 3, 'text': '广州'}]) 14 ) 15 16 gender = IntegerField(error={'required': '请选择性别', 17 'invalid': '性别必须为数字'}, 18 widget=InputRadio(text_value_list=[{'value': 1, 'text': '男', }, 19 {'value': 2, 'text': '女', }], 20 checked_value=2)) 21 22 protocol = IntegerField(error={'required': '请选择协议', 'invalid': '协议格式错误'}, 23 widget=InputSingleCheckBox(attr={'value': 1})) 24 25 favor_int_val = IntegerListField(error={'required': '请选择爱好', 'invalid': '选择爱好格式错误'}, 26 widget=InputMultiCheckBox(text_value_list=[{'value': 1, 'text': '篮球', }, 27 {'value': 2, 'text': '足球', }, 28 {'value': 3, 'text': '乒乓球', }, 29 {'value': 4, 'text': '羽毛球'}, ])) 30 31 favor_str_val = StringListField(error={'required': '请选择爱好', 'invalid': '选择爱好格式错误'}, 32 widget=InputMultiCheckBox(text_value_list=[{'value': '1', 'text': '篮球', }, 33 {'value': '2', 'text': '足球', }, 34 {'value': '3', 'text': '乒乓球', }, 35 {'value': '4', 'text': '羽毛球'}, ])) 36 37 select_str_val = StringListField(error={'required': '请选择爱好', 'invalid': '选择爱好格式错误'}, 38 widget=MultiSelect(text_value_list=[{'value': '1', 'text': '篮球', }, 39 {'value': '2', 'text': '足球', }, 40 {'value': '3', 'text': '乒乓球', }, 41 {'value': '4', 'text': '羽毛球'}, ])) 42 43 select_int_val = IntegerListField(error={'required': '请选择爱好', 'invalid': '选择爱好格式错误'}, 44 widget=MultiSelect(text_value_list=[{'value': 1, 'text': '篮球', }, 45 {'value': 2, 'text': '足球', }, 46 {'value': 3, 'text': '乒乓球', }, 47 {'value': 4, 'text': '羽毛球'}, ]))
1 class InitValueHandler(tornado.web.RequestHandler): 2 3 def get(self, *args, **kwargs): 4 form = InitValueForm(self) 5 6 init_dict = { 7 'username': 'seven', 8 'age': 18, 9 'city': 2, 10 'gender': 2, 11 'protocol': 1, 12 'favor_int_val': [1, 3], 13 'favor_str_val': ['1', '3'], 14 'select_int_val': [1, 3], 15 'select_str_val': ['1', '3'] 16 17 } 18 19 # 初始化操作,设置Form类中默认值以及默认选项 20 form.init_field_value(init_dict) 21 22 self.render('init_value.html', form=form)
动态初始值 – 处理请求的Handler(Tornado)
9、更多示例
示例源码下载:猛击这里
a. 基本使用
1 class RegisterForm(Form): 2 username = StringField(max_length=32, 3 min_length=6, 4 error={'required': '用户名不能为空', 5 'min_length': '用户名不能少于6位', 6 'max_length': '用户名不能超过32位'}) 7 8 password = StringField(max_length=32, 9 min_length=6, 10 error={'required': '密码不能为空'}, 11 widget=InputPassword()) 12 13 gender = IntegerField(error={'required': '请选择性别', 14 'invalid': '性别必须为数字'}, 15 widget=InputRadio(text_value_list=[{'value': 1, 'text': '男', }, 16 {'value': 2, 'text': '女', }], 17 checked_value=2)) 18 19 age = IntegerField(max_value=500, 20 min_value=0, 21 error={'required': '年龄不能为空', 22 'invalid': '年龄必须为数字', 23 'min_value': '年龄不能小于0', 24 'max_value': '年龄不能大于500'}) 25 26 email = EmailField(error={'required': '邮箱不能为空', 27 'invalid': '邮箱格式错误'}) 28 29 city = IntegerField(error={'required': '城市选项不能为空', 'invalid': '城市选项必须为数字'}, 30 widget=SingleSelect(text_value_list=[{'value': 1, 'text': '上海'}, 31 {'value': 2, 'text': '北京'}, 32 {'value': 3, 'text': '广州'}]) 33 ) 34 protocol = IntegerField(error={'required': '请选择协议', 'invalid': '协议格式错误'}, 35 widget=InputSingleCheckBox(attr={'value': 1})) 36 37 memo = StringField(required=False, 38 max_length=150, 39 error={'invalid': '备注格式错误', 'max_length': '备注最大长度为150字'}, 40 widget=TextArea())
b. 多选checkbox
1 class MultiCheckBoxForm(Form): 2 favor_str_val = StringListField(error={'required': '请选择爱好', 'invalid': '选择爱好格式错误'}, 3 widget=InputMultiCheckBox(text_value_list=[{'value': '1', 'text': '篮球', }, 4 {'value': '2', 'text': '足球', }, 5 {'value': '3', 'text': '乒乓球', }, 6 {'value': '4', 'text': '羽毛球'}, ])) 7 8 favor_str_val_default = StringListField(error={'required': '请选择爱好', 'invalid': '选择爱好格式错误'}, 9 widget=InputMultiCheckBox(text_value_list=[{'value': '1', 'text': '篮球', }, 10 {'value': '2', 'text': '足球', }, 11 {'value': '3', 'text': '乒乓球', }, 12 {'value': '4', 'text': '羽毛球'}, ], 13 checked_value_list=['1', '4'])) 14 15 favor_int_val = IntegerListField(error={'required': '请选择爱好', 'invalid': '选择爱好格式错误'}, 16 widget=InputMultiCheckBox(text_value_list=[{'value': 1, 'text': '篮球', }, 17 {'value': 2, 'text': '足球', }, 18 {'value': 3, 'text': '乒乓球', }, 19 {'value': 4, 'text': '羽毛球'}, ])) 20 21 favor_int_val_default = IntegerListField(error={'required': '请选择爱好', 'invalid': '选择爱好格式错误'}, 22 widget=InputMultiCheckBox(text_value_list=[{'value': 1, 'text': '篮球', }, 23 {'value': 2, 'text': '足球', }, 24 {'value': 3, 'text': '乒乓球', }, 25 {'value': 4, 'text': '羽毛球'}, ], 26 checked_value_list=[2, ]))
c、多选select
1 class MultiSelectForm(Form): 2 select_str_val = StringListField(error={'required': '请选择爱好', 'invalid': '选择爱好格式错误'}, 3 widget=MultiSelect(text_value_list=[{'value': '1', 'text': '篮球', }, 4 {'value': '2', 'text': '足球', }, 5 {'value': '3', 'text': '乒乓球', }, 6 {'value': '4', 'text': '羽毛球'}, ])) 7 8 select_str_val_default = StringListField(error={'required': '请选择爱好', 'invalid': '选择爱好格式错误'}, 9 widget=MultiSelect(text_value_list=[{'value': '1', 'text': '篮球', }, 10 {'value': '2', 'text': '足球', }, 11 {'value': '3', 'text': '乒乓球', }, 12 {'value': '4', 'text': '羽毛球'}, ], 13 selected_value_list=['1', '3'])) 14 15 select_int_val = IntegerListField(error={'required': '请选择爱好', 'invalid': '选择爱好格式错误'}, 16 widget=MultiSelect(text_value_list=[{'value': 1, 'text': '篮球', }, 17 {'value': 2, 'text': '足球', }, 18 {'value': 3, 'text': '乒乓球', }, 19 {'value': 4, 'text': '羽毛球'}, ])) 20 21 select_int_val_default = IntegerListField(error={'required': '请选择爱好', 'invalid': '选择爱好格式错误'}, 22 widget=MultiSelect(text_value_list=[{'value': 1, 'text': '篮球', }, 23 {'value': 2, 'text': '足球', }, 24 {'value': 3, 'text': '乒乓球', }, 25 {'value': 4, 'text': '羽毛球'}, ], 26 selected_value_list=[2]))
d. 动态select选项
1 class DynamicSelectForm(Form): 2 city = IntegerField(error={'required': '年龄不能为空', 'invalid': '年龄必须为数字'}, 3 widget=SingleSelect(text_value_list=[{'value': 1, 'text': '上海'}, 4 {'value': 2, 'text': '北京'}, 5 {'value': 3, 'text': '广州'}]) 6 ) 7 8 multi_favor = IntegerListField(error={'required': '请选择爱好', 'invalid': '选择爱好格式错误'}, 9 widget=MultiSelect(text_value_list=[{'value': 1, 'text': '篮球', }, 10 {'value': 2, 'text': '足球', }, 11 {'value': 3, 'text': '乒乓球', }, 12 {'value': 4, 'text': '羽毛球'}, ])) 13 14 def __init__(self, *args, **kwargs): 15 super(DynamicSelectForm, self).__init__(*args, **kwargs) 16 17 # 获取数据库中的最新数据并显示在页面上(每次创建对象都执行一次数据库操作来获取最新数据) 18 self.city.widget.text_value_list = [{'value': 1, 'text': '上海'}, 19 {'value': 2, 'text': '北京'}, 20 {'value': 3, 'text': '南京'}, 21 {'value': 4, 'text': '广州'}] 22 23 self.multi_favor.widget.text_value_list = [{'value': 1, 'text': '篮球'}, 24 {'value': 2, 'text': '足球'}, 25 {'value': 3, 'text': '乒乓球'}, 26 {'value': 4, 'text': '羽毛球'}, 27 {'value': 5, 'text': '玻璃球'}]