form表单提交数据时,获取提交数据的同时,还需要进行数据规范性的验证,
一、关于input标签中text\password的验证
(一)基本方式
1、设置一个类专门用于form验证,
2、验证类的init函数中,预置好用于验证的正则规范,
3、验证类中定义验证方法,提取用户提交数据,与正则规范比对,
#!/usr/bin/env python # -*- coding:utf-8 -*- import tornado.ioloop import tornado.web class BaseForm: def check_valid(self,handler): import re flag = True # 标记提交的数据是否通过验证 value_dict = {} # form提交数据 for key,regular in self.__dict__.items(): input_value = handler.get_argument(key) val = re.match(regular,input_value) if not val: flag = False value_dict[key] = input_value return flag,value_dict class IndexForm(BaseForm): def __init__(self): self.host = '(.*)' self.ip = '(\d+)' self.tel = '^1[3|4|5|8][0-9]\d{8}$' class LoginForm(BaseForm): def __init__(self): self.user = '^[a-zA-Z0-9_-]{4,16}$' self.pwd = '^.*(?=.{6,})(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*? ]).*$' self.email = '^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$' class IndexHandler(tornado.web.RequestHandler): def get(self): self.render('index.html') def post(self, *args, **kwargs): obj = IndexForm() # 创建form验证对象 flag,value_dict = obj.check_valid(self) # 开始form验证, print(flag,value_dict) class LoginHandler(tornado.web.RequestHandler): def get(self): self.render('login.html') def post(self, *args, **kwargs): obj = LoginForm() flag,value_dict = obj.check_valid(self) print(flag,value_dict) # 路径解析 settings = { "template_path":"views", "static_path":"statics", "static_url_prefix":"/sss/", } # 二级路由,先匹配域名, application = tornado.web.Application([ (r"/index",IndexHandler), (r"/login",LoginHandler), ],**settings) # 开启服务器,监听 if __name__ == "__main__": application.listen(8001) tornado.ioloop.IOLoop.instance().start()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login</title> </head> <body> <form action="/login" method="post"> <input type="text" name="user" placeholder="name" /> <input type="text" name="pwd" placeholder="password" /> <input type="text" name="email" placeholder="e_mail" /> <input type="submit" value="submit" /> </form> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>index</title> <script src="sss/jquery-1.12.4.min.js"></script> <style> input{margin:10px 10px;} </style> </head> <body> <form action="/index" method="post"> <input type="text" name="host" placeholder="host" /> <input type="text" name="ip" placeholder="ip" /> <input type="text" name="tel" placeholder="mobile phone" /> <input type="submit" value="submit" /> </form> </body> </html>
(二)优化版本
解决问题:1、有的输入值可以为空,2、输入值错误时提示,
#!/usr/bin/env python # -*- coding:utf-8 -*- import tornado.ioloop import tornado.web import re # ----------------------------------------------------------------------------------# class BaseTextFiled: def __init__(self,required=True,error_dict=None): self.error_dict = {} if error_dict: self.error_dict.update(error_dict) self.required = required self.error = None # 错误信息 self.value = None # 通过验证的值 self.is_valid = False # 是否通过验证的标识 def validate(self,name,input_value): ''' 单独项验证的具体操作 :param name: 需要进行验证的参数名 :param input_value: 输入值 :return: ''' if not self.required: # 用户输入可以为空 self.is_valid = True self.value = input_value else: # 用户输入不可以为空 if not input_value.strip(): # 用户输入为空,错误信息提示 if self.error_dict.get('required',None): self.error = self.error_dict['required'] else: self.error = "%s can not be empty !" % name else: # 用户输入不为空, ret= re.match(self.REGULAR,input_value) if ret: # 如果格式正确,保存相应的数值 self.is_valid = True self.value = input_value else: # 如果格式错误,提示格式错误信息 if self.error_dict.get('valid',None): self.error = self.error_dict['valid'] else: self.error = "%s is invalid !" % name class USERfiled(BaseTextFiled): # 4到16位(字母,数字,下划线,减号) REGULAR = '^[a-zA-Z0-9_-]{4,16}$' class PWDfiled(BaseTextFiled): # 最少6位,包括至少1个大写字母,1个小写字母,1个数字,1个特殊字符 REGULAR = '^.*(?=.{6,})(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*? ]).*$' class Emailfiled(BaseTextFiled): REGULAR = '^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$' class QQfiled(BaseTextFiled): # 5至11位数字 REGULAR = '^[1-9][0-9]{4,10}$' class PersonIDfiled(BaseTextFiled): # 身份证号(18位) REGULAR = '^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$' class TELfiled(BaseTextFiled): # 11位手机号码 REGULAR = '^1[3|4|5|8][0-9]\d{8}$' class IPfiled(BaseTextFiled): # ipv4地址正则 REGULAR = '^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$' class POSTfiled(BaseTextFiled): # 端口号 REGULAR = '(\d+)' class HOSTfiled(BaseTextFiled): # 主机号 REGULAR = '(.*)' # ----------------------------------------------------------------------------------# class BaseForm: def check_valid(self,handler): ''' 对form提交的整体进行验证 :param handler: 待验证的form句柄 :return: flag:验证通过标识、 error_message_dict:错误提示信息、 success_value_dict:输入的正确信息 ''' flag = True error_message_dict = {} success_value_dict = {} for key,regular in self.__dict__.items(): # 对表单进行逐项验证 input_value = handler.get_argument(key) regular.validate(key,input_value) # 具体验证方法 if regular.is_valid: success_value_dict[key] = regular.value error_message_dict[key] = "" else: error_message_dict[key] = regular.error flag = False return flag,error_message_dict,success_value_dict class IndexForm(BaseForm): def __init__(self): self.host = HOSTfiled(required = True) self.ip = IPfiled(required = True) self.post = POSTfiled(required = True) class LoginForm(BaseForm): def __init__(self): self.user = USERfiled(required = True,error_dict={'required':'不能为空','valid':'格式错误'}) self.pwd = PWDfiled(required = True,error_dict={'required':'不能为空','valid':'格式错误'}) self.email = Emailfiled(required = False) self.tel = TELfiled(required = True,error_dict={'required':'不能为空','valid':'格式错误'}) self.qq = QQfiled(required = False) self.personID = PersonIDfiled(required = True,error_dict={'required':'不能为空','valid':'格式错误'}) # ----------------------------------------------------------------------------------# class IndexHandler(tornado.web.RequestHandler): def get(self): self.render('index.html') def post(self, *args, **kwargs): obj = IndexForm() # 创建form验证对象 flag,error_message_dict,success_value_dict = obj.check_valid(self) # 开始form验证, print(flag,error_message_dict,success_value_dict) class LoginHandler(tornado.web.RequestHandler): def get(self): self.render('login.html',error_dict = None) def post(self, *args, **kwargs): obj = LoginForm() flag,error_message_dict,success_value_dict = obj.check_valid(self) if flag: self.write('is ok') else: self.render('login.html',error_dict = error_message_dict) # 路径解析 settings = { "template_path":"views", "static_path":"statics", "static_url_prefix":"/sss/", } # 二级路由,先匹配域名, application = tornado.web.Application([ (r"/index",IndexHandler), (r"/login",LoginHandler), ],**settings) # 开启服务器,监听 if __name__ == "__main__": application.listen(8001) tornado.ioloop.IOLoop.instance().start()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login</title> <style> input{margin:10px 10px} .red{border:1px solid pink;} </style> </head> <body> <form action="/login" method="post"> <input type="text" name="user" placeholder="name" class="red" /> {% if error_dict %} <span>{{error_dict['user']}}</span> {% end %} <br> <input type="password" name="pwd" placeholder="password" class="red" /> {% if error_dict %} <span>{{error_dict['pwd']}}</span> {% end %} <br> <input type="text" name="email" placeholder="e_mail" /> {% if error_dict %} <span>{{error_dict['email']}}</span> {% end %} <br> <input type="text" name="tel" placeholder="mobile phone" class="red" /> {% if error_dict %} <span>{{error_dict['tel']}}</span> {% end %} <br> <input type="text" name="qq" placeholder="qq" /> {% if error_dict %} <span>{{error_dict['qq']}}</span> {% end %} <br> <input type="text" name="personID" placeholder="personID" class="red"/> {% if error_dict %} <span>{{error_dict['personID']}}</span> {% end %} <br> <input type="submit" value="submit" /> </form> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>index</title> <script src="sss/jquery-1.12.4.min.js"></script> <style> input{margin:10px 10px;} </style> </head> <body> <form action="/index" method="post"> <input type="text" name="host" placeholder="host" /> <input type="text" name="ip" placeholder="ip" /> <input type="text" name="post" placeholder="post" /> <input type="submit" value="submit" /> </form> </body> </html>
注意:form表单提交的数据和验证的数据名称需要保持一致,
二、关于form中的checkbox验证
与text\password的验证有些许不同,具体如下:
1、获取CheckBox提交数据,使用语句self.get_arguments,

2、checkbox的验证不需要正则,只需要判断是否传值就行,

三、form上传文件的验证
验证上传文件,首先验证文件名称是否合法,如果名称合法,可设置自动上传文件,
1、获取上传文件的文件名称列表,
由于上传文件以name为单位、以列表形式存在,所以同一个name下面可以有多个文件,

2、验证文件名称是否合法,

3、名称合法后,可设置自动上传文件到指定url

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login</title> <style> input{margin:10px 10px} .red{border:1px solid pink;} </style> </head> <body> <form action="/login" method="post" enctype="multipart/form-data"> <input type="text" name="user" placeholder="name" class="red" /> {% if error_dict %} <span>{{error_dict['user']}}</span> {% end %} <br> <input type="password" name="pwd" placeholder="password" /> {% if error_dict %} <span>{{error_dict['pwd']}}</span> {% end %} <br> <input type="text" name="email" placeholder="e_mail" /> {% if error_dict %} <span>{{error_dict['email']}}</span> {% end %} <br> <input type="text" name="tel" placeholder="mobile phone" class="red" /> {% if error_dict %} <span>{{error_dict['tel']}}</span> {% end %} <br> <input type="text" name="qq" placeholder="qq" /> {% if error_dict %} <span>{{error_dict['qq']}}</span> {% end %} <br> <input type="text" name="personID" placeholder="personID" class="red"/> {% if error_dict %} <span>{{error_dict['personID']}}</span> {% end %} <br><br> <span>爱好:</span><br> <span>足球</span><input type="checkbox" value="1" name="favor"> <span>篮球</span><input type="checkbox" value="2" name="favor"> <span>乒乓球</span><input type="checkbox" value="3" name="favor"> <span>羽毛球</span><input type="checkbox" value="4" name="favor"> {% if error_dict %} <span>{{error_dict['favor']}}</span> {% end %} <br><br> <span>性别:</span><br> <span>男</span><input type="radio" value="1" name="sex" /> <span>女</span><input type="radio" value="0" name="sex" /> {% if error_dict %} <span>{{error_dict['sex']}}</span> {% end %} <br><br> <textarea name="balabala" class="red" style="height:50px;width:500px;" placeholder="想说些什么..."></textarea> {% if error_dict %} <span>{{error_dict['balabala']}}</span> {% end %} <br><br> <input type="file" name="myPic" /> <input type="file" name="myPic" /> {% if error_dict %} <span>{{error_dict['myPic']}}</span> {% end %} <br><br> <input type="submit" value="submit" /> </form> </body> </html>
#!/usr/bin/env python # -*- coding:utf-8 -*- import tornado.ioloop import tornado.web import re import os # ----------------------------------------------------------------------------------# class BaseTextFiled: def __init__(self,required=True,error_dict=None): self.error_dict = {} if error_dict: self.error_dict.update(error_dict) self.required = required self.error = None # 错误信息 self.value = None # 通过验证的值 self.is_valid = False # 是否通过验证的标识 def validate(self,name,input_value): ''' 单独项验证的具体操作 :param name: 需要进行验证的参数名 :param input_value: 输入值 :return: ''' if not self.required: # 用户输入可以为空 self.is_valid = True self.value = input_value else: # 用户输入不可以为空 if not input_value.strip(): # 用户输入为空,错误信息提示 if self.error_dict.get('required',None): self.error = self.error_dict['required'] else: self.error = "%s can not be empty !" % name else: # 用户输入不为空, ret= re.match(self.REGULAR,input_value) if ret: # 如果格式正确,保存相应的数值 self.is_valid = True self.value = input_value else: # 如果格式错误,提示格式错误信息 if self.error_dict.get('valid',None): self.error = self.error_dict['valid'] else: self.error = "%s is invalid !" % name class USERfiled(BaseTextFiled): # 4到16位(字母,数字,下划线,减号) REGULAR = '^[a-zA-Z0-9_-]{4,16}$' class PWDfiled(BaseTextFiled): # 最少6位,包括至少1个大写字母,1个小写字母,1个数字,1个特殊字符 REGULAR = '^.*(?=.{6,})(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*? ]).*$' class Emailfiled(BaseTextFiled): REGULAR = '^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$' class QQfiled(BaseTextFiled): # 5至11位数字 REGULAR = '^[1-9][0-9]{4,10}$' class PersonIDfiled(BaseTextFiled): # 身份证号(18位) REGULAR = '^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$' class TELfiled(BaseTextFiled): # 11位手机号码 REGULAR = '^1[3|4|5|8][0-9]\d{8}$' class IPfiled(BaseTextFiled): # ipv4地址正则 REGULAR = '^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$' class POSTfiled(BaseTextFiled): # 端口号 REGULAR = '(\d+)' class HOSTfiled(BaseTextFiled): # 主机号 REGULAR = '(.*)' class BALABALAfiled(BaseTextFiled): # 最多200个字符 REGULAR = '^[\s\S]{,200}$' # ----------------------------------------------------------------------------------# class CHOICEfiled(BaseTextFiled): def validate(self,name,input_value): if not self.required: # 用户输入可以为空 self.is_valid = True self.value = input_value else: # 用户输入不可以为空 if not input_value: if self.error_dict.get('required',None): self.error = self.error_dict['required'] else: self.error = "%s can not be empty !" % name else: self.is_valid = True self.value = input_value # ----------------------------------------------------------------------------------# class UPLOADfiled(BaseTextFiled): # 接收文件格式:pdf、img、py REGULAR = '^(\w+\.pdf)|(\w+\.img)|(\w+\.py)$' def validate(self,name,all_files_name_list): self.name = name # 用于文件save函数调用 self.is_valid = True if not self.required: # 用户输入可以为空 self.value = all_files_name_list else: # 用户输入不可以为空 if not all_files_name_list: self.is_valid = False if self.error_dict.get('required',None): self.error = self.error_dict['required'] else: self.error = "%s can not be empty !" % name else: # 上传文件名称验证 self.value = [] for each_file_name in all_files_name_list: # 验证文件名字列表,有一个不符合要求,就验证失败 ret= re.match(self.REGULAR,each_file_name) if ret: self.value.append(each_file_name) else: self.is_valid = False if self.error_dict.get('valid',None): self.error = self.error_dict['valid'] else: self.error = "%s is invalid !" % name break def save(self,request,path='statics/img'): # 全部验证成功后,上传文件 file_metas = request.files.get(self.name,[]) for meta in file_metas: fileName = os.path.join(path,meta['filename']) if fileName and fileName in self.value: with open(fileName,'wb') as upFile: upFile.write(meta['body']) # ----------------------------------------------------------------------------------# class BaseForm: def check_valid(self,handler): ''' 对form提交的整体进行验证 :param handler: 待验证的form句柄 :return: flag:验证通过标识、 error_message_dict:错误提示信息、 success_value_dict:输入的正确信息 ''' flag = True error_message_dict = {} success_value_dict = {} for key,regular in self.__dict__.items(): # 对表单进行逐项验证 if type(regular) == CHOICEfiled: input_value = handler.get_arguments(key) elif type(regular) == UPLOADfiled: input_value = [] if handler.request.files.get('myPic',[]): file_metas = handler.request.files['myPic'] for meta in file_metas: fileName = meta['filename'] input_value.append(fileName) else: input_value = handler.get_argument(key) regular.validate(key,input_value) # 具体验证方法 if regular.is_valid: success_value_dict[key] = regular.value error_message_dict[key] = "" else: error_message_dict[key] = regular.error flag = False return flag,error_message_dict,success_value_dict class IndexForm(BaseForm): def __init__(self): self.host = HOSTfiled(required = True) self.ip = IPfiled(required = True) self.post = POSTfiled(required = True) self.favor = FAVORfiled(required = True) class LoginForm(BaseForm): def __init__(self): self.user = USERfiled(required = True,error_dict={'required':'不能为空','valid':'格式错误'}) self.pwd = PWDfiled(required = False) self.email = Emailfiled(required = False) self.tel = TELfiled(required = True,error_dict={'required':'不能为空','valid':'格式错误'}) self.qq = QQfiled(required = False) self.personID = PersonIDfiled(required = True,error_dict={'required':'不能为空','valid':'格式错误'}) self.favor = CHOICEfiled(required = True,error_dict={'required':'请选择'}) self.sex = CHOICEfiled(required = True,error_dict={'required':'请选择'}) self.balabala = BALABALAfiled(required = True,error_dict={'required':'不能为空','valid':'不超过200个字符'}) self.myPic = UPLOADfiled(required = True,error_dict={'required':'请上传文件','valid':'仅接收如下格式的文件:pdf、img、py'}) # ----------------------------------------------------------------------------------# class IndexHandler(tornado.web.RequestHandler): def get(self): self.render('index.html') def post(self, *args, **kwargs): obj = IndexForm() # 创建form验证对象 flag,error_message_dict,success_value_dict = obj.check_valid(self) # 开始form验证, print(flag,error_message_dict,success_value_dict) class LoginHandler(tornado.web.RequestHandler): def get(self): self.render('login.html',error_dict = None) def post(self, *args, **kwargs): obj = LoginForm() flag,error_message_dict,success_value_dict = obj.check_valid(self) if flag: obj.myPic.save(self.request,path='statics/img') # 自动上传文件 print('1',flag,error_message_dict,success_value_dict) self.write('is ok') else: self.render('login.html',error_dict = error_message_dict) # 路径解析 settings = { "template_path":"views", "static_path":"statics", "static_url_prefix":"/sss/", } # 二级路由,先匹配域名, application = tornado.web.Application([ (r"/index",IndexHandler), (r"/login",LoginHandler), ],**settings) # 开启服务器,监听 if __name__ == "__main__": application.listen(8001) tornado.ioloop.IOLoop.instance().start()
浙公网安备 33010602011771号