zoukankan      html  css  js  c++  java
  • python web框架——扩展Django&tornado

    一 Django自定义分页

       目的:自定义分页功能,并把它写成模块(注意其中涉及到的python基础知识)

        models.py文件

    # Create your models here.
    class UserList(models.Model):
        username = models.CharField(max_length=32)
        age = models.IntegerField()

        分页模块page.py文件

    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    __author__ = 'mcp'
    
    # 导入后台标记字符串安全的模块
    from django.utils.safestring import mark_safe
    
    # 自定义的分页类
    class Pager(object):
        def __init__(self, current_page):
            self.current_page = int(current_page)
        # 让方法伪装成属性,加装饰器
        @property
        def start(self):
            return (self.current_page-1)*10
        @property
        def end(self):
            return self.current_page*10
    
        def page_str(self,all_item,base_url):
            all_page,div = divmod(all_item,10)
            if div>0:
                all_page += 1
    
            pager_list = []
    
            if all_page <= 11:
                start = 1
                end = all_page
            else:
                if self.current_page < 6:
                    start = 1
                    end =11 + 1
                  else:
                    start = self.current_page - 5
                    end = self.current_page + 6
                      if self.current_page + 6 > all_page:
                        start = all_page - 11
                        end = all_page + 1
    
            for i in range(start,end):
                # 注意单双引号的使用,/user_list/?page=
                if i == self.current_page:
                    tmp = '<a style="color:red;font-size:20px;"href="%s%d">%d</a>' %(base_url,i,i,)
               else:
                    tmp = '<a href="%s%d">%d</a>' %(base_url,i,i,)
               pager_list.append(tmp)
    
            # 上一页
            if self.current_page > 1:
                pre_page = '<a href="%s%d">上一页</a>' %(base_url,self.current_page - 1)
           else:
                pre_page = '<a href="javascript:void(0);">上一页</a>'
             # 下一页
            if self.current_page < all_page:
                next_page = '<a href="%s%d">下一页</a>' %(base_url,self.current_page + 1)
           else:
                next_page = '<a href="javascript:void(0);">下一页</a>'
            
             #在最前面插入上一页按钮
            pager_list.insert(0,pre_page)
            #在最后面插入下一页按钮
            pager_list.append(next_page)
    
            # return ''.join(pager_list)
             # 直接在后台标记字符串是安全的
            return  mark_safe(''.join(pager_list))

        views.py文件

    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    
    from django.shortcuts import render
    from django.shortcuts import HttpResponse
    from app01 import models
    # 导入自定义分页模块
    from app01 import page # Create your views here. def user_list(request): # 先创建100条表数据 # for item in range(101,500): # dic = {'username':'name%d' %item, 'age':item} # models.UserList.objects.create(**dic) # 再打印数据库中有多少条数据 # print models.UserList.objects.all().count() # 获取第0-9条数据,分片 # print type(models.UserList.objects.all()) #<class 'django.db.models.query.QuerySet'> # result = models.UserList.objects.all()[0:10] current_page = request.GET.get('page',1) # 注意current_page为字符串类型,要转换成整型 # current_page = int(current_page) # start = (current_page-1)*10 # end = current_page*10 # result = models.UserList.objects.all()[start:end] pager_obj = page.Pager(current_page) # result = models.UserList.objects.all()[pager_obj.start():pager_obj.end()] # 下面这句是从Django ORM中取数据,相当于在数据库中执行如下sql语句 # SELECT "app01_userlist"."id", "app01_userlist"."username", "app01_userlist"."age"
    # FROM "app01_userlist" LIMIT 10 OFFSET 490
    result = models.UserList.objects.all()[pager_obj.start:pager_obj.end] # 打印Django ORM中在底层实际执行的sql语句 print result.query # 每页显示10条数据 # 共100条 all_item = models.UserList.objects.all().count() # 把下面的代码封装到函数中了 pager_str = pager_obj.page_str(all_item,"/user_list/?page=") # all_page,div = divmod(all_item,10) # if div>0: # all_page += 1 # # pager_str = "" # for i in range(1,all_page+1): # # 注意单双引号的使用 # tmp = '<a href="/user_list/?page=%d">%d</a>' %(i,i,) # pager_str += tmp return render(request,'user_list.html',{'result':result,'pager_str':pager_str})

        user_list.html文件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    
        <style>
            a{
                padding: 5px;
            }
        </style>
    </head>
    <body>
        <h1>测试</h1>
        <table>
            <tbody>
               {% for line in result %}
               <tr>
                  <td>{{ line.username }}</td>
                  <td>{{ line.age }}</td>
               </tr>
               {% endfor %}
            </tbody>
        </table>
    {#    <div>#}
    {#        <a href="/user_list/?page=1">1</a>#}
    {#        <a href="/user_list/?page=2">2</a>#}
    {#        <a href="/user_list/?page=3">3</a>#}
    {#        <a href="/user_list/?page=4">4</a>#}
    {#        <a>5</a>#}
    {#        <a>6</a>#}
    {#        <a>7</a>#}
    {#        <a>8</a>#}
    {#        <a>9</a>#}
    {#        <a>10</a>#}
    {#    </div>#}
        <div>
            {#在前端标记后台传的字符串是安全的#}
            {#{{ pager_str | safe }}#}
            {{ pager_str }}
        </div>
    </body>
    </html>

        自定义分页模块涉及到的知识以及注意点:

        (1)Django ORM

        (2)python中类、属性、div方法以及封装特性

        (3)XSS攻击(在前端或后端标记字符串是安全的)

        (4)python相关基础知识以及装饰器

    二 自定义Tornado的Session框架

       1 知识回顾

       Tornado中没有Session部分,这需要开发者去自己扩展Tornado的Session框架。在自定义Session框架之前,先来回顾下Django中Session和Cookie的知识:

        用户登录过程中的Session和Cookie:
            1、在服务端随机生成一串字符;
            2、将该字符串写到浏览器端,同时将该字符串存储在服务端,存储形式为字典,其中该字符串为key(服务端Session为字典形式);
            3、在服务端Session中设置相应值,比如是否已经登录。

    操作Session:
        获取Session:request.session[key]
        设置Session:reqeust.session[key] = value
        删除Session:del request[key]
        
    request.session.set_expiry(value)
    * 如果value为整数,则Session会在value秒后失效;
    * 如果value为datatime或timedelta,则Session会在这个时间后失效;
    * 如果value为0,则用户关闭浏览器后Session就会失效;
    * 如果value为None,则Session会依赖全局Session失效策略。

        2 自定义Session

         (1)知识储备

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
      
    class Foo(object):
      
        def __getitem__(self, key):
            print  '__getitem__',key
      
        def __setitem__(self, key, value):
            print '__setitem__',key,value
      
        def __delitem__(self, key):
            print '__delitem__',key
      
    # 创建obj对象
    obj = Foo()
    # 获取key为'k1'的元素,这时会调用__getitem__方法
    result = obj['k1']
    # 给key为'k2'的元素赋值,这时会调用__setitem__方法
    #obj['k2'] = 'wupeiqi'
    # 删除key为'k3'的元素,这时会调用__delitem__方法
    #del obj['k3'] 

        (2)Session框架代码

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import tornado.ioloop
    import tornado.web
    from hashlib import sha1
    import os, time
    
    session_container = {}
    
    create_session_id = lambda: sha1('%s%s' % (os.urandom(16), time.time())).hexdigest()
    
    class Session(object):
    
        session_id = "__sessionId__"
    
        def __init__(self, request):
            #当请求过来时,先利用get_cookie方法获取cookie值,目的是为了确定是否存在Cookie,如果有则不生成,否则生成。
            session_value = request.get_cookie(Session.session_id)
            #如果Cookie不存在,则生成Cookie(创建随机字符串)
            if not session_value:
                self._id = create_session_id()
            else:
                #如果Cookie存在,则直接将获取的Cookie值赋值给_id字段
                self._id = session_value
            #设置Session值
            request.set_cookie(Session.session_id, self._id)
        
        #特殊方法:获取值时调用的方法 
        def __getitem__(self, key):
            ret = None
            try:
                #获取Session值方法
                ret =  session_container[self._id][key]
            except Exception,e:
                pass
            return ret
    
        #特殊方法:设置值时调用的方法 
        def __setitem__(self, key, value):
            #判断是否存在Cookie值,如果存在设置相应的值
            if session_container.has_key(self._id):
                session_container[self._id][key] = value
            #如果不存在,则生成相应的字典数据,类似:{'Cookie值':{'IS_LOGIN':'True'}}
            else: 
                session_container[self._id] = {key: value}
        #特殊方法:删除值时调用的方法 
        def __delitem__(self, key):
            del session_container[self._id][key]
    
    class BaseHandler(tornado.web.RequestHandler):
        #扩展了Tornado的initialize方法,这个方法默认为空方法
        def initialize(self):
            '''
            这里initialize的self指向谁?
            obj = LoginHandler()
            obj.initialize() ==>LoginHandler类中没有initialize这个方法,该方法继承自它的父类
            所以initialize的self就是LoginHandler对象
            '''
            
            #执行Session类的构造方法,同时把LoginHandler对象传参给Session类的构造方法
            self.my_session = Session(self) 
    
    class MainHandler(BaseHandler):
    
        def get(self):
            ret = self.my_session['is_login']
            if ret:
                self.write('index')
            else:
                self.redirect("/login")
    
    class LoginHandler(BaseHandler):
        def get(self):
            '''
            当用户浏览器访问服务端时,就应该给浏览器写入cookie了,但是这里没有写?
            那在哪里写入cookie呢?上面定义的相关Handler类都是继承自RequestHandler,这次继承的是自定义的BaseHandler类,
            继承自定义的类,然后在类中扩展了initialize方法,获取用户cookie或者写cookie都可以在此方法中操作
            '''
            # self.set_cookie()
            # self.get_cookie()
    
            self.render('login.html', **{'status': ''})
    
        def post(self, *args, **kwargs):
            #获取用户提交的用户名和密码
            username = self.get_argument('username')
            password = self.get_argument('pwd')
            if username == 'wupeiqi' and password == '123':
                #如果认证通过,就可以访问这个self.my_session对象,然后就可以把Cookie写入字典中。
                self.my_session['is_login'] = 'true'
                self.redirect('/index')
            else:
                self.render('login.html', **{'status': '用户名或密码错误'})
    
    settings = {
        'template_path': 'template',
        'static_path': 'static',
        'static_url_prefix': '/static/',
        'cookie_secret': 'abcdefgh',
        'login_url': '/login'
    }
    
    application = tornado.web.Application([
        #创建两个URL 分别对应MainHandler和LoginHandler
        (r"/index", MainHandler),
        (r"/login", LoginHandler),
    ], **settings)
    
    
    if __name__ == "__main__":
        application.listen(8888)
        tornado.ioloop.IOLoop.instance().start()

        (3)分布式Session框架

         上面使用Tornado预留扩展方法initialize和Class类实现了自定义的Session框架,下面探讨如何实现分布式Session框架。上面自定义的Session框架中,Session默认保存在session_container字典中。实际生产环境中,Session也可以存储在Redis,memcache,mysql中,如果把session存储在单台服务器上,那么存在着数据不安全或数据量大时满足不了性能要求。这时可以考虑分布式(假设有3台服务器存储Session),那么可以分别存储在A、B、C上:

        当用户第1次访问时,通过权重和hash计算把session加入到hash环中,实现分布式存储;当用户第2次携带Cookie访问时,通过计算找到相应的Session值并进行认证。

      一致性哈希

    #!/usr/bin/env python
    #coding:utf-8
    
    import sys
    import math
    from bisect import bisect
    
    
    if sys.version_info >= (2, 5):
        import hashlib
        md5_constructor = hashlib.md5
    else:
        import md5
        md5_constructor = md5.new
    
    
    class HashRing(object):
        #一致性哈希 
        def __init__(self,nodes):
            '''
            初始化: 包含存储节点以及节点对应的权重
                    默认每1个节点有32个虚拟节点
                    对于权重,通过多创建虚拟节点来实现
                    如:nodes = [
                            {'host':'127.0.0.1:8000','weight':1},
                            {'host':'127.0.0.1:8001','weight':2},
                            {'host':'127.0.0.1:8002','weight':1},
                        ]
            '''
            
            self.ring = dict()
            self._sorted_keys = []
    
            self.total_weight = 0
            
            self.__generate_circle(nodes)
              
        def __generate_circle(self,nodes):
            for node_info in nodes:
                self.total_weight += node_info.get('weight',1)
                
            for node_info in nodes:
                weight = node_info.get('weight',1)
                node = node_info.get('host',None)
                    
                virtual_node_count = math.floor((32*len(nodes)*weight) / self.total_weight)
                for i in xrange(0,int(virtual_node_count)):
                    key = self.gen_key_thirty_two( '%s-%s' % (node, i) )
                    if self._sorted_keys.__contains__(key):
                        raise Exception('该节点已经存在.')
                    self.ring[key] = node
                    self._sorted_keys.append(key)
                
        def add_node(self,node):
            ''' 
            新建节点node: 新添加节点格式为:{'host':'127.0.0.1:8002','weight':1},其中第1个元素表示节点,
    第2个元素表示该节点的权重。
    ''' node = node.get('host',None) if not node: raise Exception('节点的地址不能为空.') weight = node.get('weight',1) self.total_weight += weight nodes_count = len(self._sorted_keys) + 1 virtual_node_count = math.floor((32 * nodes_count * weight) / self.total_weight) for i in xrange(0,int(virtual_node_count)): key = self.gen_key_thirty_two( '%s-%s' % (node, i) ) if self._sorted_keys.__contains__(key): raise Exception('该节点已经存在.') self.ring[key] = node self._sorted_keys.append(key) def remove_node(self,node): ''' 移除节点node: 要移除的节点'127.0.0.1:8000' ''' for key,value in self.ring.items(): if value == node: del self.ring[key] self._sorted_keys.remove(key) def get_node(self,string_key): ''' 获取string_key所在的节点 ''' pos = self.get_node_pos(string_key) if pos is None: return None return self.ring[ self._sorted_keys[pos]].split(':') def get_node_pos(self,string_key): ''' 获取string_key所在的节点的索引 ''' if not self.ring: return None key = self.gen_key_thirty_two(string_key) nodes = self._sorted_keys pos = bisect(nodes, key) return pos def gen_key_thirty_two(self, key): m = md5_constructor() m.update(key) return long(m.hexdigest(), 16) def gen_key_sixteen(self,key): b_key = self.__hash_digest(key) return self.__hash_val(b_key, lambda x: x) def __hash_val(self, b_key, entry_fn): return (( b_key[entry_fn(3)] << 24)|(b_key[entry_fn(2)] << 16)|(b_key[entry_fn(1)] << 8)| b_key[entry_fn(0)] ) def __hash_digest(self, key): m = md5_constructor() m.update(key) return map(ord, m.digest()) """ nodes = [ {'host':'127.0.0.1:8000','weight':1}, {'host':'127.0.0.1:8001','weight':2}, {'host':'127.0.0.1:8002','weight':1}, ] ring = HashRing(nodes) result = ring.get_node('98708798709870987098709879087') print result """

        分布式Session框架代码:

    from hashlib import sha1
    import os, time
    
    create_session_id = lambda: sha1('%s%s' % (os.urandom(16), time.time())).hexdigest()
    
    class Session(object):
    
        session_id = "__sessionId__"
    
        def __init__(self, request):
            session_value = request.get_cookie(Session.session_id)
            if not session_value:
                self._id = create_session_id()
            else:
                self._id = session_value
            request.set_cookie(Session.session_id, self._id)
    
        def __getitem__(self, key):
            # 根据 self._id ,在一致性哈西中找到其对应的服务器IP
            # 找到相对应的redis服务器,如: r = redis.StrictRedis(host='localhost', port=6379, db=0)
            # 使用python redis api 链接
            # 获取数据,即:
            # return self._redis.hget(self._id, name)
    
        def __setitem__(self, key, value):
            # 根据 self._id ,在一致性哈西中找到其对应的服务器IP
            # 使用python redis api 链接
            # 设置session
            # self._redis.hset(self._id, name, value)
    
        def __delitem__(self, key):
            # 根据 self._id 找到相对应的redis服务器
            # 使用python redis api 链接
            # 删除,即:
            return self._redis.hdel(self._id, name)

    自定义Tornado的Form框架

       python web框架中,只有Django提供了form框架。在Tornado等其他python web框架中,需要自定义form框架。Django中的form验证流程:
           用户输入 ==》request.post ==> obj = Form(request.POST) ==> obj.is_valid()
       存在问题:request在获取用户输入时并不知道用户输入的个数,Form表单内可能有1个也有可能有多个输入,这是Django中Form框架存在的问题。

       Form(模型绑定)有两个主要功能:
        (1)自动生成html表单
        (2)用户输入验证 

       1 简单的form框架

       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>

       index.py文件

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import tornado.ioloop
    import tornado.web
    from hashlib import sha1
    import os, time
    import 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):
            #循环当前类中的成员,注意此种方法
            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
    
    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()

       2  自定义form框架优化版

         (1)验证字段写成相应的类;

         (2)类的继承

         (3)ListForm

      自定义Form完整代码

    #!/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()

    参考资料:

           http://www.cnblogs.com/wupeiqi/articles/5341480.html

         http://www.cnblogs.com/luotianshuai/p/5482612.html

  • 相关阅读:
    别人走的路-1
    抽象类跟接口的区别
    一个类实现多个接口的demo
    servlet+jdbc+javabean其实跟ssh差不多
    什么是shell
    设置cookie倒计时让让表单自动提交
    变量、基本数据类型
    编程语言、添加环境变量、变量
    Java优先队列一些问题
    JavaScript学习-JSON
  • 原文地址:https://www.cnblogs.com/maociping/p/5351340.html
Copyright © 2011-2022 走看看