[py]一步一步实现tornado form验证

来源:互联网 发布:淘宝led散热片 编辑:程序博客网 时间:2024/05/24 06:09

第一关

第二关

第四关

第五关

第六关

以下是各步逐渐成熟的代码.关数和上面图无关.

相关git代码

第零关: 一个index表单

#!/usr/bin/env python# -*- coding:utf-8 -*-import tornado.ioloopimport tornado.webfrom hashlib import sha1import os, timeimport re# 创建form类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):        # 循环当前类中的成员,注意此种方法        flag = True        value_dict = {}        for key, regular in self.__dict__.items():            '''            通过request.get_argument()来获取用户前端输入的值            在循环时,不需要关心前端输入值的个数,这里以自定义方法为主            '''            post_value = request.get_argument(key)            # 前端提交的数据与自定义的正则表达式进行匹配验证            ret = re.match(regular, post_value)            print(key,"---------",ret, "---------",post_value)            # 如果结果 结果为None时候,即只要有一项不匹配,就返回false,flag = False            if not ret:                flag = False            # {"ip":192.168.1.1,"port":8080,....}            value_dict[key] = post_value        # print(value_dict)        return flag,value_dictclass MainHandler(tornado.web.RequestHandler):    def get(self):        self.render('index.html')    def post(self, *args, **kwargs):        obj = MainForm()        is_valid, value_dict= obj.check_valid(self)        # self.write('ok')        # 如果全部验证成功,则打印        if is_valid:            print(value_dict)        self.write("ok")settings = {    'template_path': 'templates',    'static_path': 'statics',    'static_url_prefix': '/static/',    'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh',    'login_url': '/login'}application = tornado.web.Application([    (r"/index", MainHandler),], **settings)if __name__ == "__main__":    print("http://127.0.0.1:8888/index")    application.listen(8888)    tornado.ioloop.IOLoop.instance().start()

index.html

<!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>

第一关: 2个表单index和home需要验证

form11.html

#!/usr/bin/env python# -*- coding:utf-8 -*-import tornado.ioloopimport tornado.webfrom hashlib import sha1import os, timeimport re# 创建indexform类class IndexForm(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):        # 循环当前类中的成员,注意此种方法        flag = True        value_dict = {}        for key, regular in self.__dict__.items():            '''            通过request.get_argument()来获取用户前端输入的值            在循环时,不需要关心前端输入值的个数,这里以自定义方法为主            '''            post_value = request.get_argument(key)            # 前端提交的数据与自定义的正则表达式进行匹配验证            ret = re.match(regular, post_value)            print(key,"---------",ret, "---------",post_value)            # 如果结果 结果为None时候,即只要有一项不匹配,就返回false,flag = False            if not ret:                flag = False            # {"ip":192.168.1.1,"port":8080,....}            value_dict[key] = post_value        # print(value_dict)        return flag,value_dict# 创建homeform类class HomeForm(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}$"    # 验证    def check_valid(self, request):        # 循环当前类中的成员,注意此种方法        flag = True        value_dict = {}        for key, regular in self.__dict__.items():            '''            通过request.get_argument()来获取用户前端输入的值            在循环时,不需要关心前端输入值的个数,这里以自定义方法为主            '''            post_value = request.get_argument(key)            # 前端提交的数据与自定义的正则表达式进行匹配验证            ret = re.match(regular, post_value)            print(key,"---------",ret, "---------",post_value)            # 如果结果 结果为None时候,即只要有一项不匹配,就返回false,flag = False            if not ret:                flag = False            # {"ip":192.168.1.1,"port":8080,....}            value_dict[key] = post_value        # print(value_dict)        return flag,value_dictclass IndexHandler(tornado.web.RequestHandler):    def get(self):        self.render('index.html')    def post(self, *args, **kwargs):        obj = IndexForm()        is_valid, value_dict= obj.check_valid(self)        # self.write('ok')        # 如果全部验证成功,则打印        if is_valid:            print(value_dict)        self.write("ok")class HomeHandler(tornado.web.RequestHandler):    def get(self):        self.render('home.html')    def post(self, *args, **kwargs):        obj = HomeForm()        is_valid, value_dict= obj.check_valid(self)        # self.write('ok')        # 如果全部验证成功,则打印        if is_valid:            print(value_dict)        self.write("ok")settings = {    'template_path': 'templates',    'static_path': 'statics',    'static_url_prefix': '/static/',    'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh',    'login_url': '/login'}application = tornado.web.Application([    (r"/index", IndexHandler),    (r"/home", HomeHandler),], **settings)if __name__ == "__main__":    print("http://127.0.0.1:8888/index")    application.listen(8888)    tornado.ioloop.IOLoop.instance().start()

index.html

<!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>

home.html

<!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="/home" method="post">        <p>hostname: <input type="text" name="host" /> </p>        <p>ip: <input type="text" name="ip" /> </p>        <input type="submit" />    </form></body></html>

第二关:2个表单index和home需要验证-继承

  • 完整code
    form12.py
#!/usr/bin/env python# -*- coding:utf-8 -*-import reimport tornado.web# 验证类class BaseForm(object):    # 验证    def check_valid(self, request):        # 循环当前类中的成员,注意此种方法        flag = True        value_dict = {}        for key, regular in self.__dict__.items():            '''            通过request.get_argument()来获取用户前端输入的值            在循环时,不需要关心前端输入值的个数,这里以自定义方法为主            '''            post_value = request.get_argument(key)            # 前端提交的数据与自定义的正则表达式进行匹配验证            ret = re.match(regular, post_value)            print(key, "---------", ret, "---------", post_value)            # 如果结果 结果为None时候,即只要有一项不匹配,就返回false,flag = False            if not ret:                flag = False            # {"ip":192.168.1.1,"port":8080,....}            value_dict[key] = post_value        # print(value_dict)        return flag, value_dict# 创建indexform类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}$'# 创建homeform类class HomeForm(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}$"class IndexHandler(tornado.web.RequestHandler):    def get(self):        self.render('index.html')    def post(self, *args, **kwargs):        obj = IndexForm()        is_valid, value_dict = obj.check_valid(self)        # self.write('ok')        # 如果全部验证成功,则打印        if is_valid:            print(value_dict)        self.write("ok")class HomeHandler(tornado.web.RequestHandler):    def get(self):        self.render('home.html')    def post(self, *args, **kwargs):        obj = HomeForm()        is_valid, value_dict = obj.check_valid(self)        # self.write('ok')        # 如果全部验证成功,则打印        if is_valid:            print(value_dict)        self.write("ok")settings = {    'template_path': 'templates',    'static_path': 'statics',    'static_url_prefix': '/static/',    'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh',    'login_url': '/login'}application = tornado.web.Application([    (r"/index", IndexHandler),    (r"/home", HomeHandler),], **settings)if __name__ == "__main__":    print("http://127.0.0.1:8888/index")    application.listen(8888)    tornado.ioloop.IOLoop.instance().start()## 不能区分是哪里错了

home.html

<!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="/home" method="post">        <p>hostname: <input type="text" name="host" /> </p>        <p>ip: <input type="text" name="ip" /> </p>        <input type="submit" />    </form></body></html>

index.html

<!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>

第三关:封装字段

理解这个,需要一点前戏, 猛戳这里
以ipfield为例

  • 效果

如果没自定义信息,如果输入格式错误,则报系统内置错误
如果自定义了错误信息,则优先报自定义的错误

  • 逻辑关系

  • 代码逻辑
    这里写图片描述

  • 完整code
    form13.py
#!/usr/bin/env python# -*- coding:utf-8 -*-import reimport tornado.webclass IPField:    REGULAR = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$"    # error_dict 自定义报错信息    def __init__(self, error_dict=None, required=True):        self.error_dict = {}        # 如果自定义了错误信息,更新错误        if error_dict:            self.error_dict.update(error_dict)        # 保存required        self.required = required        # 错误信息        self.error = None        # 是否匹配        self.is_valid = None        # 匹配成功后值是多少        self.value = None    # name 字段名(便于提示错误)    # input_value 用于输入值,用于验证    def validate(self, name, input_value):        '''        :param name: 字段名(便于提示错误)        :param input_value:        :return: input_value 用于输入值,用于验证        '''        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:                    # 提示ip不能为空                    self.error = "%s is required" % name            else:                # 用户输入了ip,接下来判断ip格式                ret = re.match(IPField.REGULAR, input_value)  # 静态字段IPField.REGULAR                if ret:                    # 匹配成功                    self.is_valid = True                    self.value = ret.group()                    # self.value = ret.input_value                else:                    # 匹配失败 构造错误信息                    if self.error_dict.get("valid", None):                        self.error = self.error_dict["valid"]                    else:                        self.error = "%s is invalid" % name# 验证类class BaseForm(object):    # 验证    def check_valid(self, handle):        # 循环当前类中的成员,注意此种方法        flag = True        value_dict = {}        # 错误信息        error_msg_dict = {}        success_value_dict = {}        for key, regular in self.__dict__.items():            # key: ip            # regular: IPField对象            # input_value 用户输入的值            input_value = handle.get_argument(key)            regular.validate(key, input_value)            # 如果验证成功            if regular.is_valid:                # pass                success_value_dict[key] = regular.value            else:                error_msg_dict[key] = regular.error                # 如果验证失败                flag = False            value_dict[key] = input_value        return flag, success_value_dict, error_msg_dict# 创建homeform类class HomeForm(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.ip = IPField(required=True,                          error_dict={"required": "别闹,不能为空", "valid": "格式错了,兄弟..."})  # required=True 必须要写        # self.ip = IPField()class HomeHandler(tornado.web.RequestHandler):    def get(self):        self.render('home1.html')    def post(self, *args, **kwargs):        obj = HomeForm()        is_valid, success_dict, error_dict = obj.check_valid(self)        # self.write('ok')        # 如果全部验证成功,则打印        if is_valid:            print("sucess", success_dict)        else:            print("error", error_dict)settings = {    'template_path': 'templates',    'static_path': 'statics',    'static_url_prefix': '/static/',    'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh',    'login_url': '/login'}application = tornado.web.Application([    (r"/home", HomeHandler),], **settings)if __name__ == "__main__":    print("http://127.0.0.1:8888/index")    application.listen(8888)    tornado.ioloop.IOLoop.instance().start()

home1.html

<!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="/home" method="post">        <p>ip: <input type="text" name="ip" /> </p>        <input type="submit" />    </form></body></html>