zoukankan      html  css  js  c++  java
  • 自定义Web组件

    一、Session

    1、面向对象基础

    面向对象中通过索引的方式访问对象,需要内部实现 __getitem__ 、__delitem__、__setitem__方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #!/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 = Foo()
    result = obj['k1']
    #obj['k2'] = 'wupeiqi'
    #del obj['k1']

    2、Tornado扩展

    Tornado框架中,默认执行Handler的get/post等方法之前默认会执行 initialize方法,所以可以通过自定义的方式使得所有请求在处理前执行操作...

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    class BaseHandler(tornado.web.RequestHandler):
       
        def initialize(self):
            self.xxoo = "wupeiqi"
       
       
    class MainHandler(BaseHandler):
       
        def get(self):
            print(self.xxoo)
            self.write('index')
     
    class IndexHandler(BaseHandler):
       
        def get(self):
            print(self.xxoo)
            self.write('index')

    3、session

    session其实就是定义在服务器端用于保存用户回话的容器,其必须依赖cookie才能实现。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import config
    from hashlib import sha1
    import os
    import time
    
    create_session_id = lambda: sha1(bytes('%s%s' % (os.urandom(16), time.time()), encoding='utf-8')).hexdigest()
    
    
    class SessionFactory:
    
        @staticmethod
        def get_session_obj(handler):
            obj = None
    
            if config.SESSION_TYPE == "cache":
                obj = CacheSession(handler)
            elif config.SESSION_TYPE == "memcached":
                obj = MemcachedSession(handler)
            elif config.SESSION_TYPE == "redis":
                obj = RedisSession(handler)
            return obj
    
    
    class CacheSession:
        session_container = {}
        session_id = "__sessionId__"
    
        def __init__(self, handler):
            self.handler = handler
            client_random_str = handler.get_cookie(CacheSession.session_id, None)
            if client_random_str and client_random_str in CacheSession.session_container:
                self.random_str = client_random_str
            else:
                self.random_str = create_session_id()
                CacheSession.session_container[self.random_str] = {}
    
            expires_time = time.time() + config.SESSION_EXPIRES
            handler.set_cookie(CacheSession.session_id, self.random_str, expires=expires_time)
    
        def __getitem__(self, key):
            ret = CacheSession.session_container[self.random_str].get(key, None)
            return ret
    
        def __setitem__(self, key, value):
            CacheSession.session_container[self.random_str][key] = value
    
        def __delitem__(self, key):
            if key in CacheSession.session_container[self.random_str]:
                del CacheSession.session_container[self.random_str][key]
    
    
    class RedisSession:
        def __init__(self, handler):
            pass
    
    
    class MemcachedSession:
        def __init__(self, handler):
            pass
    自定义session

    4、分布式Session

    # -*- coding: utf-8 -*-
    """
        hash_ring
        ~~~~~~~~~~~~~~
        Implements consistent hashing that can be used when
        the number of server nodes can increase or decrease (like in memcached).
    
        Consistent hashing is a scheme that provides a hash table functionality
        in a way that the adding or removing of one slot
        does not significantly change the mapping of keys to slots.
    
        More information about consistent hashing can be read in these articles:
    
            "Web Caching with Consistent Hashing":
                http://www8.org/w8-papers/2a-webserver/caching/paper2.html
    
            "Consistent hashing and random trees:
            Distributed caching protocols for relieving hot spots on the World Wide Web (1997)":
                http://citeseerx.ist.psu.edu/legacymapper?did=38148
    
    
        Example of usage::
    
            memcache_servers = ['192.168.0.246:11212',
                                '192.168.0.247:11212',
                                '192.168.0.249:11212']
    
            ring = HashRing(memcache_servers)
            server = ring.get_node('my_key')
    
        :copyright: 2008 by Amir Salihefendic.
        :license: BSD
    """
    
    import math
    import sys
    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=None, weights=None):
            """`nodes` is a list of objects that have a proper __str__ representation.
            `weights` is dictionary that sets weights to the nodes.  The default
            weight is that all nodes are equal.
            """
            self.ring = dict()
            self._sorted_keys = []
    
            self.nodes = nodes
    
            if not weights:
                weights = {}
            self.weights = weights
    
            self._generate_circle()
    
        def _generate_circle(self):
            """Generates the circle.
            """
            total_weight = 0
            for node in self.nodes:
                total_weight += self.weights.get(node, 1)
    
            for node in self.nodes:
                weight = 1
    
                if node in self.weights:
                    weight = self.weights.get(node)
    
                factor = math.floor((40*len(self.nodes)*weight) / total_weight)
    
                for j in range(0, int(factor)):
                    b_key = self._hash_digest( '%s-%s' % (node, j) )
    
                    for i in range(0, 3):
                        key = self._hash_val(b_key, lambda x: x+i*4)
                        self.ring[key] = node
                        self._sorted_keys.append(key)
    
            self._sorted_keys.sort()
    
        def get_node(self, string_key):
            """Given a string key a corresponding node in the hash ring is returned.
    
            If the hash ring is empty, `None` is returned.
            """
            pos = self.get_node_pos(string_key)
            if pos is None:
                return None
            return self.ring[ self._sorted_keys[pos] ]
    
        def get_node_pos(self, string_key):
            """Given a string key a corresponding node in the hash ring is returned
            along with it's position in the ring.
    
            If the hash ring is empty, (`None`, `None`) is returned.
            """
            if not self.ring:
                return None
    
            key = self.gen_key(string_key)
    
            nodes = self._sorted_keys
            pos = bisect(nodes, key)
    
            if pos == len(nodes):
                return 0
            else:
                return pos
    
        def iterate_nodes(self, string_key, distinct=True):
            """Given a string key it returns the nodes as a generator that can hold the key.
    
            The generator iterates one time through the ring
            starting at the correct position.
    
            if `distinct` is set, then the nodes returned will be unique,
            i.e. no virtual copies will be returned.
            """
            if not self.ring:
                yield None, None
    
            returned_values = set()
            def distinct_filter(value):
                if str(value) not in returned_values:
                    returned_values.add(str(value))
                    return value
    
            pos = self.get_node_pos(string_key)
            for key in self._sorted_keys[pos:]:
                val = distinct_filter(self.ring[key])
                if val:
                    yield val
    
            for i, key in enumerate(self._sorted_keys):
                if i < pos:
                    val = distinct_filter(self.ring[key])
                    if val:
                        yield val
    
        def gen_key(self, key):
            """Given a string key it returns a long value,
            this long value represents a place on the hash ring.
    
            md5 is currently used because it mixes well.
            """
            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.encode('utf-8'))
            # return map(ord, m.digest())  # python 2 
            return list(m.digest())  # pyhton 3
    一致性哈希(hash_ring.py)
    session

    二、表单(form)验证

    在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

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

    View Code
  • 相关阅读:
    tcp流协议产生的粘包问题和解决方案
    使用fork并发处理多个client的请求和对等通信p2p
    最简单的回射客户/服务器程序、time_wait 状态
    C/S程序的一般流程和基本socket函数
    socket概述和字节序、地址转换函数
    IP数据报格式和IP地址路由
    利用ARP和ICMP协议解释ping命令
    TCP/IP协议栈与数据报封装
    从汇编角度来理解linux下多层函数调用堆栈运行状态
    read/write函数与(非)阻塞I/O的概念
  • 原文地址:https://www.cnblogs.com/maple-shaw/p/8021787.html
Copyright © 2011-2022 走看看