web 框架6 tornado的form表单验证组件开发
前面介绍了 session pager分页 的组件开发
http://www.cnblogs.com/liujianzuo888/articles/5727814.html
表单验证
在Web程序中往往包含大量的表单验证的工作,如:判断输入是否为空,是否符合规则。
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <link href="{{static_url("commons.css")}}" rel="stylesheet" /> </head> <body> <h1>hello</h1> <form action="/index" method="post"> <p>hostname: <input type="text" name="host" /> </p> <p>ip: <input type="text" name="ip" /> </p> <p>port: <input type="text" name="port" /> </p> <p>phone: <input type="text" name="phone" /> </p> <input type="submit" /> </form> </body> </html>
#!/usr/bin/env python # -*- coding:utf-8 -*- import tornado.ioloop import tornado.web from hashlib import sha1 import os, time import re class MainForm(object): def __init__(self): self.host = "(.*)" self.ip = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" self.port = '(\d+)' self.phone = '^1[3|4|5|8][0-9]\d{8}$' def check_valid(self, request): form_dict = self.__dict__ for key, regular in form_dict.items(): post_value = request.get_argument(key) # 让提交的数据 和 定义的正则表达式进行匹配 ret = re.match(regular, post_value) print key,ret,post_value class MainHandler(tornado.web.RequestHandler): def get(self): self.render('index.html') def post(self, *args, **kwargs): obj = MainForm() result = obj.check_valid(self) self.write('ok') settings = { 'template_path': 'template', 'static_path': 'static', 'static_url_prefix': '/static/', 'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh', 'login_url': '/login' } application = tornado.web.Application([ (r"/index", MainHandler), ], **settings) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()
由于验证规则可以代码重用,所以可以如此定义:
#!/usr/bin/env python # -*- coding:utf-8 -*- import tornado.ioloop import tornado.web import re class Field(object): def __init__(self, error_msg_dict, required): self.id_valid = False self.value = None self.error = None self.name = None self.error_msg = error_msg_dict self.required = required def match(self, name, value): self.name = name if not self.required: self.id_valid = True self.value = value else: if not value: if self.error_msg.get('required', None): self.error = self.error_msg['required'] else: self.error = "%s is required" % name else: ret = re.match(self.REGULAR, value) if ret: self.id_valid = True self.value = ret.group() else: if self.error_msg.get('valid', None): self.error = self.error_msg['valid'] else: self.error = "%s is invalid" % name class IPField(Field): REGULAR = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" def __init__(self, error_msg_dict=None, required=True): error_msg = {} # {'required': 'IP不能为空', 'valid': 'IP格式错误'} if error_msg_dict: error_msg.update(error_msg_dict) super(IPField, self).__init__(error_msg_dict=error_msg, required=required) class IntegerField(Field): REGULAR = "^\d+$" def __init__(self, error_msg_dict=None, required=True): error_msg = {'required': '数字不能为空', 'valid': '数字格式错误'} if error_msg_dict: error_msg.update(error_msg_dict) super(IntegerField, self).__init__(error_msg_dict=error_msg, required=required) class CheckBoxField(Field): def __init__(self, error_msg_dict=None, required=True): error_msg = {} # {'required': 'IP不能为空', 'valid': 'IP格式错误'} if error_msg_dict: error_msg.update(error_msg_dict) super(CheckBoxField, self).__init__(error_msg_dict=error_msg, required=required) def match(self, name, value): self.name = name if not self.required: self.id_valid = True self.value = value else: if not value: if self.error_msg.get('required', None): self.error = self.error_msg['required'] else: self.error = "%s is required" % name else: if isinstance(name, list): self.id_valid = True self.value = value else: if self.error_msg.get('valid', None): self.error = self.error_msg['valid'] else: self.error = "%s is invalid" % name class FileField(Field): REGULAR = "^(\w+\.pdf)|(\w+\.mp3)|(\w+\.py)$" def __init__(self, error_msg_dict=None, required=True): error_msg = {} # {'required': '数字不能为空', 'valid': '数字格式错误'} if error_msg_dict: error_msg.update(error_msg_dict) super(FileField, self).__init__(error_msg_dict=error_msg, required=required) def match(self, name, value): self.name = name self.value = [] if not self.required: self.id_valid = True self.value = value else: if not value: if self.error_msg.get('required', None): self.error = self.error_msg['required'] else: self.error = "%s is required" % name else: m = re.compile(self.REGULAR) if isinstance(value, list): for file_name in value: r = m.match(file_name) if r: self.value.append(r.group()) self.id_valid = True else: self.id_valid = False if self.error_msg.get('valid', None): self.error = self.error_msg['valid'] else: self.error = "%s is invalid" % name break else: if self.error_msg.get('valid', None): self.error = self.error_msg['valid'] else: self.error = "%s is invalid" % name def save(self, request, upload_path=""): file_metas = request.files[self.name] for meta in file_metas: file_name = meta['filename'] with open(file_name,'wb') as up: up.write(meta['body']) class Form(object): def __init__(self): self.value_dict = {} self.error_dict = {} self.valid_status = True def validate(self, request, depth=10, pre_key=""): self.initialize() self.__valid(self, request, depth, pre_key) def initialize(self): pass def __valid(self, form_obj, request, depth, pre_key): """ 验证用户表单请求的数据 :param form_obj: Form对象(Form派生类的对象) :param request: Http请求上下文(用于从请求中获取用户提交的值) :param depth: 对Form内容的深度的支持 :param pre_key: Html中name属性值的前缀(多层Form时,内部递归时设置,无需理会) :return: 是否验证通过,True:验证成功;False:验证失败 """ depth -= 1 if depth < 0: return None form_field_dict = form_obj.__dict__ for key, field_obj in form_field_dict.items(): print key,field_obj if isinstance(field_obj, Form) or isinstance(field_obj, Field): if isinstance(field_obj, Form): # 获取以key开头的所有的值,以参数的形式传至 self.__valid(field_obj, request, depth, key) continue if pre_key: key = "%s.%s" % (pre_key, key) if isinstance(field_obj, CheckBoxField): post_value = request.get_arguments(key, None) elif isinstance(field_obj, FileField): post_value = [] file_list = request.request.files.get(key, None) for file_item in file_list: post_value.append(file_item['filename']) else: post_value = request.get_argument(key, None) print post_value # 让提交的数据 和 定义的正则表达式进行匹配 field_obj.match(key, post_value) if field_obj.id_valid: self.value_dict[key] = field_obj.value else: self.error_dict[key] = field_obj.error self.valid_status = False class ListForm(object): def __init__(self, form_type): self.form_type = form_type self.valid_status = True self.value_dict = {} self.error_dict = {} def validate(self, request): name_list = request.request.arguments.keys() + request.request.files.keys() index = 0 flag = False while True: pre_key = "[%d]" % index for name in name_list: if name.startswith(pre_key): flag = True break if flag: form_obj = self.form_type() form_obj.validate(request, depth=10, pre_key="[%d]" % index) if form_obj.valid_status: self.value_dict[index] = form_obj.value_dict else: self.error_dict[index] = form_obj.error_dict self.valid_status = False else: break index += 1 flag = False class MainForm(Form): def __init__(self): # self.ip = IPField(required=True) # self.port = IntegerField(required=True) # self.new_ip = IPField(required=True) # self.second = SecondForm() self.fff = FileField(required=True) super(MainForm, self).__init__() # # class SecondForm(Form): # # def __init__(self): # self.ip = IPField(required=True) # self.new_ip = IPField(required=True) # # super(SecondForm, self).__init__() class MainHandler(tornado.web.RequestHandler): def get(self): self.render('index.html') def post(self, *args, **kwargs): # for i in dir(self.request): # print i # print self.request.arguments # print self.request.files # print self.request.query # name_list = self.request.arguments.keys() + self.request.files.keys() # print name_list # list_form = ListForm(MainForm) # list_form.validate(self) # # print list_form.valid_status # print list_form.value_dict # print list_form.error_dict # obj = MainForm() # obj.validate(self) # # print "验证结果:", obj.valid_status # print "符合验证结果:", obj.value_dict # print "错误信息:" # for key, item in obj.error_dict.items(): # print key,item # print self.get_arguments('favor'),type(self.get_arguments('favor')) # print self.get_argument('favor'),type(self.get_argument('favor')) # print type(self.get_argument('fff')),self.get_argument('fff') # print self.request.files # obj = MainForm() # obj.validate(self) # print obj.valid_status # print obj.value_dict # print obj.error_dict # print self.request,type(self.request) # obj.fff.save(self.request) # from tornado.httputil import HTTPServerRequest # name_list = self.request.arguments.keys() + self.request.files.keys() # print name_list # print self.request.files,type(self.request.files) # print len(self.request.files.get('fff')) # obj = MainForm() # obj.validate(self) # print obj.valid_status # print obj.value_dict # print obj.error_dict # obj.fff.save(self.request) self.write('ok') settings = { 'template_path': 'template', 'static_path': 'static', 'static_url_prefix': '/static/', 'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh', 'login_url': '/login' } application = tornado.web.Application([ (r"/index", MainHandler), ], **settings) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()
练习 由简单到复杂的 演变
1 第一个简单的form验证
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </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="port" placeholder="port"> <input type="text" name="phone" placeholder="phone"> <input type="submit" value="提交"> </form> <div>{{xx}}</div> </body> </html>
#!/usr/bin/env python #_*_coding:utf-8_*_ import tornado.web import tornado.ioloop import re class MainForm(object): def __init__(self): self.host = "(.*)" self.ip = "(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" self.port = "(\d+)" self.phone = "^1[3|4|5|7|8][0-9]\d{8}" def check_valid(self,handle): flag = True value_dic ={} for key,regular in self.__dict__.items(): input_value = handle.get_argument(key) val = re.match(regular,input_value) print(key,input_value,val,regular) if not val: flag = False value_dic[key] = input_value return flag,value_dic class IndexHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): self.render("index.html",xx=11) # self.write("func([11,22,33])") def post(self, *args, **kwargs): print(123) obj = MainForm() # 获取用户输入内容 #和正则表达式匹配 is_valid, value_dict = obj.check_valid(self) print(is_valid) #如果全部验证成功,将用户输入的所有数据放入obj.value_dit if is_valid: print(value_dict) settings = { "template_path":"views", "static_path":"statics", "static_url_prefix":"/statics/", } application = tornado.web.Application([ (r"/index",IndexHandler) ],**settings) if __name__ == '__main__': application.listen(8001) tornado.ioloop.IOLoop.instance().start()
2 第二稍微复杂的 附带注释 复选框验证
附带checkbox提交到后台 home.html
if type(regular) == ChechBoxFiled: input_value = handle.get_arguments(key) # 获取的是复选框字典
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form> <input type="text" name="host"> <input type="text" name="ip"> <input type="text" name="port"> <input type="text" name="phone"> <input type="submit" value="提交"> </form> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>home</title> </head> <body> <form action="/home" method="post"> <input type="text" name="ip" placeholder="ip"> <input type="text" name="host" placeholder="host"> <p> <input type="checkbox" name="favor" value="1" /> 篮球; <input type="checkbox" name="favor" value="2" /> 足球; <input type="checkbox" name="favor" value="3" /> 玻璃球; </p> {% if error_dict %} <span>{{ error_dict["ip"] }}</span> {% end %} <input type="submit" > </form> </body> </html>
import tornado.ioloop import tornado.web import re # 检测输入框的ip class IPFiled: REGULAR = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" #静态 字段 def __init__(self, error_dict=None, required=True): # 封装了错误信息 81行实例化时候封装的 self.error_dict = {} if error_dict:# 81 行实例化 传入的错误信息,如果不传 则为None,则不会执行 self.error_dict.update(error_dict) #将实例化时候 传入的错误信息封装 self.required = required # # 81 行实例化 传入的是否为空字段,默认是浏览器输入不许为空 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: # 当比如81行我们传入可以为空的时候即False时候走这一段代码 # 用户输入可以为空 self.is_valid = True # 设置封装值为真 self.value = input_value #将空值封装 else: #当81行要求输入不为空时候 # 用户有输入,这一要验证正则了。 if not input_value.strip(): # 输入为空,返回错误信息。 错误信息字典 if self.error_dict.get('required',None): # 81行定义的错误信息。如果未定义则自己定义 self.error = self.error_dict['required'] else: self.error = "%s is required" % name #默认错误信息 else: # 输入不为空, ret = re.match(IPFiled.REGULAR, input_value) #获取 静态字段的正则字符串,跟用户的input输入内容匹配 if ret: # 匹配通过, self.is_valid = True self.value = input_value else: #匹配不通过,返回错误字典 if self.error_dict.get('valid', None): #81 行定义的错误信息,如果未定义则自己定义 self.error = self.error_dict['valid'] else: self.error = "%s is invalid" % name # 检测 输入框的字符串 class StringFiled: REGULAR = "^(.*)$" #静态 字段 def __init__(self, error_dict=None, required=True): # 封装了错误信息 82行实例化时候封装的 self.error_dict = {} if error_dict:# 82 行实例化 传入的错误信息,如果不传 则为None,则不会执行 self.error_dict.update(error_dict) #将实例化时候 传入的错误信息封装 self.required = required # # 81 行实例化 传入的是否为空字段,默认是浏览器输入不许为空 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: # 当比如82行我们传入可以为空的时候即False时候走这一段代码 # 用户输入可以为空 self.is_valid = True # 设置封装值为真 self.value = input_value #将空值封装 else: #当81行要求输入不为空时候 # 用户有输入,这一要验证正则了。 if not input_value.strip(): # 输入为空,返回错误信息。 错误信息字典 if self.error_dict.get('required',None): # 82行定义的错误信息。如果未定义则自己定义 self.error = self.error_dict['required'] else: self.error = "%s is required" % name #默认错误信息 else: # 输入不为空, ret = re.match(IPFiled.REGULAR, input_value) #获取 静态字段的正则字符串,跟用户的input输入内容匹配 if ret: # 匹配通过, self.is_valid = True self.value = input_value else: #匹配不通过,返回错误字典 if self.error_dict.get('valid', None): #82 行定义的错误信息,如果未定义则自己定义 self.error = self.error_dict['valid'] else: self.error = "%s is invalid" % name # 检测输入框的复选框 class ChechBoxFiled: def __init__(self, error_dict=None, required=True): # 封装了错误信息 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: 字段名 favor :param input_value: 用户表单中输入的内容,列表None, [1,2] :return: """ 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 is required" % name else: self.is_valid = True self.value = input_value class BaseForm: # 公共的类的方法,不用重复写 def check_valid(self, handle): # 94 行调用了这个方法,继承找到的 flag = True # 默认为true error_message_dict = {} success_value_dict = {} for key, regular in self.__dict__.items(): # 对象的所有项 self。ip IPFiled对象 # key: ip ..... # handle: HomeIndex对象,self.get_... self. # regular: IPFiled(required=True) if type(regular) == ChechBoxFiled: input_value = handle.get_arguments(key) # 获取的是复选框字典 else: input_value = handle.get_argument(key) # 获取浏览器传输过来的输入框的name值 # input_value = 用户输入的值 # 将具体的验证,放在IPFiled对象中 regular.validate(key, input_value) # 由于regular是字段验证对象,于是跳到其valiate方法这里是IPField 由于是 IPFiled对象的validate方法,传入前端input框的name值 if regular.is_valid: success_value_dict[key] = regular.value else: error_message_dict[key] = regular.error flag = False return flag, success_value_dict, error_message_dict # class IndexForm(BaseForm): # def __init__(self): # self.host = "(.*)" # self.ip = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" # self.port = '(\d+)' # self.phone = '^1[3|4|5|8][0-9]\d{8}$' class HomeForm(BaseForm): def __init__(self): # 构造函数 # IPFiled是另一个类,实例化 ,传入的是我们自定义信息,如果我们不传入,会返回给我们内部自定义信息。 # 这时候 封装的self.ip 是一个对象。执行IPField的init方法,封装一些属性 # 下面的ip host favor 必须与前端的input 的name相同 self.ip = IPFiled(required=True, error_dict={'required': "别闹,别整空的..", "valid": "骚年,格式错误了"}) self.host = StringFiled(required=False) self.favor = ChechBoxFiled(required=True,error_dict={'required' : "复选框不能为空"}) class HomeHandler(tornado.web.RequestHandler): def get(self): self.render('home.html', error_dict=None) def post(self, *args, **kwargs): obj = HomeForm() # 实例化HomeForm类 每种验证都是一个类,而这些验证的类需要验证合法性的方法我们用类的继承放在另一个类中 # 获取用户输入的内容 # 和正则表达式匹配 is_valid, success_dict, error_dict = obj.check_valid(self) #将 HomeHandler类对象传入 获取对象继承的类的方法的返回值 执行 BaseForm类的check_valid方法 if is_valid: # print('success', success_dict) else: print('error', error_dict) self.render('home.html', error_dict=error_dict) settings = { 'template_path': 'views', 'static_path': 'statics', 'static_url_prefix': '/statics/', } application = tornado.web.Application([ (r"/home", HomeHandler), ], **settings) if __name__ == "__main__": application.listen(8001) tornado.ioloop.IOLoop.instance().start()
3 第三个 文件上传验证 home.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form> <input type="text" name="host"> <input type="text" name="ip"> <input type="text" name="port"> <input type="text" name="phone"> <input type="submit" value="提交"> </form> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>home</title> </head> <body> <form action="/home" method="post" enctype="multipart/form-data"> <input type="text" name="ip" placeholder="ip"> <input type="text" name="host" placeholder="host"> <p> <input type="checkbox" name="favor" value="1" /> 篮球; <input type="checkbox" name="favor" value="2" /> 足球; <input type="checkbox" name="favor" value="3" /> 玻璃球; </p> <p> <input type="file" name="fafafa" /> <input type="file" name="fafafa" /> </p> {% if error_dict and 'ip' in error_dict %} <span>{{ error_dict["ip"] }}</span> {% end %} <input type="submit" > </form> </body> </html>
import tornado.ioloop import tornado.web import re # 检测输入框的ip class IPFiled: REGULAR = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" #静态 字段 def __init__(self, error_dict=None, required=True): # 封装了错误信息 81行实例化时候封装的 self.error_dict = {} if error_dict:# 81 行实例化 传入的错误信息,如果不传 则为None,则不会执行 self.error_dict.update(error_dict) #将实例化时候 传入的错误信息封装 self.required = required # # 81 行实例化 传入的是否为空字段,默认是浏览器输入不许为空 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: # 当比如81行我们传入可以为空的时候即False时候走这一段代码 # 用户输入可以为空 self.is_valid = True # 设置封装值为真 self.value = input_value #将空值封装 else: #当81行要求输入不为空时候 # 用户有输入,这一要验证正则了。 if not input_value.strip(): # 输入为空,返回错误信息。 错误信息字典 if self.error_dict.get('required',None): # 81行定义的错误信息。如果未定义则自己定义 self.error = self.error_dict['required'] else: self.error = "%s is required" % name #默认错误信息 else: # 输入不为空, ret = re.match(IPFiled.REGULAR, input_value) #获取 静态字段的正则字符串,跟用户的input输入内容匹配 if ret: # 匹配通过, self.is_valid = True self.value = input_value else: #匹配不通过,返回错误字典 if self.error_dict.get('valid', None): #81 行定义的错误信息,如果未定义则自己定义 self.error = self.error_dict['valid'] else: self.error = "%s is invalid" % name # 检测 输入框的字符串 class StringFiled: # REGULAR = "^(.*)$" #静态 字段 REGULAR = "(.*)" #静态 字段 def __init__(self, error_dict=None, required=True): # 封装了错误信息 82行实例化时候封装的 self.error_dict = {} if error_dict:# 82 行实例化 传入的错误信息,如果不传 则为None,则不会执行 self.error_dict.update(error_dict) #将实例化时候 传入的错误信息封装 self.required = required # # 81 行实例化 传入的是否为空字段,默认是浏览器输入不许为空 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: # 当比如82行我们传入可以为空的时候即False时候走这一段代码 # 用户输入可以为空 self.is_valid = True # 设置封装值为真 self.value = input_value #将空值封装 else: #当81行要求输入不为空时候 # 用户有输入,这一要验证正则了。 if not input_value.strip(): # 输入为空,返回错误信息。 错误信息字典 if self.error_dict.get('required',None): # 82行定义的错误信息。如果未定义则自己定义 self.error = self.error_dict['required'] else: self.error = "%s is required" % name #默认错误信息 else: # 输入不为空, ret = re.match(IPFiled.REGULAR, input_value) #获取 静态字段的正则字符串,跟用户的input输入内容匹配 if ret: # 匹配通过, self.is_valid = True self.value = input_value else: #匹配不通过,返回错误字典 if self.error_dict.get('valid', None): #82 行定义的错误信息,如果未定义则自己定义 self.error = self.error_dict['valid'] else: self.error = "%s is invalid" % name # 检测输入框的复选框 class ChechBoxFiled: def __init__(self, error_dict=None, required=True): # 封装了错误信息 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: 字段名 favor :param input_value: 用户表单中输入的内容,列表None, [1,2] :return: """ 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 is required" % name else: self.is_valid = True self.value = input_value #文件上传验证 class FileFiled: REGULAR = "^(\w+\.pdf)|(\w+\.mp3)|(\w+\.py)$" def __init__(self, error_dict=None, required=True): # 封装了错误信息 self.error_dict = {} if error_dict: self.error_dict.update(error_dict) self.required = required self.error = None # 错误信息 self.value = [] self.is_valid = True self.name = None self.success_file_name_list = [] def validate(self, name, all_file_name_list): """ :param name: 字段名 :param all_file_name_list: 所有文件文件名 :return: """ self.name = name if not self.required: # 用户输入可以为空 self.is_valid = True self.value = all_file_name_list else: if not all_file_name_list: self.is_valid = False if self.error_dict.get('required',None): self.error = self.error_dict['required'] else: self.error = "%s is required" % name else: # 循环所有的文件名 for file_name in all_file_name_list: ret = re.match(FileFiled.REGULAR, file_name) if not ret: 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 else: self.value.append(file_name) def save(self, request, path='statics'): import os # 所有文件列表 file_metas = request.files.get(self.name) print("filemetas",12213213,file_metas) # 循环文件列表 temp_list = [] for meta in file_metas: # 每一个文件的文件名 file_name = meta['filename'] # self.value:[1.py, 2.py] 【statics/1.py statics/2.py】 new_file_name = os.path.join(path, file_name) if file_name and file_name in self.value: temp_list.append(new_file_name) with open(new_file_name, 'wb') as up: up.write(meta['body']) self.value = temp_list class BaseForm: # 公共的类的方法,不用重复写 def check_valid(self, handle): # 94 行调用了这个方法,继承找到的 flag = True # 默认为true error_message_dict = {} success_value_dict = {} for key, regular in self.__dict__.items(): # 对象的所有项 self。ip IPFiled对象 print(key,":key") # key: ip host ..... # handle: HomeIndex对象,self.get_... self. # regular: IPFiled(required=True) if type(regular) == ChechBoxFiled: input_value = handle.get_arguments(key) # 获取的是复选框字典 elif type(regular) == FileFiled: # 获取文件名 print("file123333333",handle.request.files) file_list= handle.request.files.get(key) # [{'body':"xx",'filename1':"xx"},{'body':"xx",'filename':"xx"}] print(file_list) input_value = [ ] if file_list: #如果前端有传入文件 for item in file_list: # 循环对象request封装的file信息 input_value.append(item['filename']) #获取所有文件名 print(item["filename"]) else: input_value = handle.get_argument(key) # 获取浏览器传输过来的输入框的name值 # input_value = 用户输入的值 # 将具体的验证,放在IPFiled对象中 regular.validate(key, input_value) # 由于regular是字段验证对象,于是跳到其valiate方法这里是IPField 由于是 IPFiled对象的validate方法,传入前端input框的name值 if regular.is_valid: success_value_dict[key] = regular.value else: error_message_dict[key] = regular.error flag = False return flag, success_value_dict, error_message_dict # class IndexForm(BaseForm): # def __init__(self): # self.host = "(.*)" # self.ip = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" # self.port = '(\d+)' # self.phone = '^1[3|4|5|8][0-9]\d{8}$' class HomeForm(BaseForm): def __init__(self): # 构造函数 # IPFiled是另一个类,实例化 ,传入的是我们自定义信息,如果我们不传入,会返回给我们内部自定义信息。 # 这时候 封装的self.ip 是一个对象。执行IPField的init方法,封装一些属性 # 下面的ip host favor 必须与前端的input 的name相同 self.ip = IPFiled(required=True, error_dict={'required': "别闹,别整空的..", "valid": "骚年,格式错误了"}) self.host = StringFiled(required=False) self.favor = ChechBoxFiled(required=True,error_dict={'required' : "复选框不能为空"}) self.fafafa = FileFiled(required=True) class HomeHandler(tornado.web.RequestHandler): def get(self): self.render('home.html', error_dict=None) def post(self, *args, **kwargs): obj = HomeForm() # 实例化HomeForm类 每种验证都是一个类,而这些验证的类需要验证合法性的方法我们用类的继承放在另一个类中 # 获取用户输入的内容 # 和正则表达式匹配 is_valid, success_dict, error_dict = obj.check_valid(self) #将 HomeHandler类对象传入 获取对象继承的类的方法的返回值 执行 BaseForm类的check_valid方法 if is_valid: # print('success', success_dict) obj.fafafa.save(self.request) #传入文件对象 else: print('error', error_dict) self.render('home.html', error_dict=error_dict) settings = { 'template_path': 'views', 'static_path': 'statics', 'static_url_prefix': '/statics/', } application = tornado.web.Application([ (r"/home", HomeHandler), ], **settings) if __name__ == "__main__": application.listen(8001) tornado.ioloop.IOLoop.instance().start()