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>
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()
Python逻辑程序

由于验证规则可以代码重用,所以可以如此定义:

#!/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()
完整版 武sir

 

练习 由简单到复杂的 演变

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>
index.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()
app.py

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>
index.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>
home.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()
注释 app.py

 

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>
index.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>
home.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()
app.py

 

 

 

posted @ 2016-08-22 10:53  众里寻,阑珊处  阅读(387)  评论(0编辑  收藏  举报
返回顶部