1. 程式人生 > >基於Tornado自定制仿Django的Session以及Form組件

基於Tornado自定制仿Django的Session以及Form組件

contain spl exists redirect cookies nco one pytho actor

一、session

1.Session本質是保存在服務器端的數據,可以看作是鍵值對。

用戶第一次打開網站頁面
- 生成一段隨機字符串,作為value發給客戶端瀏覽器,客戶端帶著字符串獲取對應的session
- 在session中保存,隨機字符串作為key,value={‘user‘:‘Mitsui‘,‘pwd‘:123....}

2.session模塊代碼:
import time
import hashlib
import settings

def get_random_str():
    """
    獲取作為session key的隨機字符串
    :return:
    """
    md5 = hashlib.md5()
    md5.update(str(time.time()).encode(‘utf-8‘))
    return md5.hexdigest()

class RedisSession(object):
    def __init__(self,handler):
        """
        基於Redis在服務端存儲session
        :param handler:
        """
        self.handler = handler
        self.session_id = settings.SESSION_ID
        self.expires = settings.EXPIRERS
        self.initial()

    @property
    def conn(self):
        import redis
        conn = redis.Redis(host=‘192.168.xx.xx‘,port=6379)
        return conn

    def initial(self):
        client_random_str = self.handler.get_cookie(self.session_id)

        if client_random_str and self.conn.exists(client_random_str):
            self.random_str = client_random_str
        else:
            self.random_str = get_random_str()

        expires = time.time() + self.expires
        self.handler.set_cookie(self.session_id,self.random_str,expires=expires)
        #除了對瀏覽器cookies設置超時時間,也需要對redis數據設置超時時間,可以定時清除數據節省空間
        self.conn.expire(self.random_str,self.expires)

    def __getitem__(self, item):
        """
        取session,item為key,如self.session[‘user‘]
        :param item:
        :return:
        """
        import json
        #由於Python數據類型直接存入redis後受到轉換,因此在存儲時會先dumps,相應的取值時會先loads。
        data_str = self.conn.hget(self.random_str,item)
        if data_str:
            return json.loads(data_str)
        else:
            return None

    def __setitem__(self, key, value):
        """
        設置session
        :param key:
        :param value:
        :return:
        """
        import json
        self.conn.hset(self.random_str,key,json.dumps(value))

    def __delitem__(self, key):
        """
        刪除session
        :param key:
        :return:
        """
        self.conn.hdel(self.random_str)

class CacheSession(object):

    container = {}

    def __init__(self,handler):
        """
        普通的內存存取session
        :param handler: 視圖函數傳進的self,可以使用get_cookie等方法
        """
        self.handler = handler
        self.session_id = settings.SESSION_ID   #存儲在瀏覽器的cookies的key
        self.expires = settings.EXPIRERS        #超時時間
        self.initial()

    def initial(self):
        """

        :return:
        """
        client_random_str = self.handler.get_cookie(self.session_id)
        if client_random_str and client_random_str in self.container:
            #如果session中已經有值,賦原值刷新超時時間
            self.random_str = client_random_str
        else:
            #沒有則獲取隨機字符串 作為session的key存儲在內存中container,並設置超時時間,
            self.random_str = get_random_str()
            self.container[self.random_str] = {}
        expires = time.time() + self.expires
        self.handler.set_cookie(self.session_id,self.random_str,expires=expires)

    def __getitem__(self, item):
        """
        獲取session
        :param item:key,  session[‘user‘]
        :return:
        """
        return self.container[self.random_str].get(item)

    def __setitem__(self, key, value):
        """
        設置session
        :param key:  session[‘user‘]
        :param value:    =user
        :return:
        """
        self.container[self.random_str][key] = value

    def __delitem__(self, key):
        """
        刪除session   del self.session時觸發
        :param key:
        :return:
        """
        if key in self.container[self.random_str]:
            del self.container[self.random_str][key]



class SessionFactory(object):
    """
    讀取配置文件,根據配置文件返回定制的session類
    """
    @staticmethod
    def get_session():
        import settings
        import importlib
        engine = settings.SESSION_ENGINE
        module_path,cls_name = engine.rsplit(‘.‘,maxsplit=1)
        md = importlib.import_module(module_path)
        cls = getattr(md,cls_name)
        return cls

 

3.基於Tornado的使用:

import tornado.ioloop
import tornado.web
from tornado.web import RequestHandler
from session_code import SessionFactory

class SessionHandler(object):
    def initialize(self,*args,**kwargs):
        cls = SessionFactory.get_session()
        # cls是CacheSession對象,RedisSession對象
        #執行cls的init方法
        self.session = cls(self)


class LoginHandler(SessionHandler,RequestHandler):
    """
    init方法執行之後,執行get 跟post方法之前,會先執行initialize方法,
    這裏用多繼承的方法繼承自SessionHandler,執行initialize方法,獲取
    CacheSession或者RedisSession對象的session方法
    """

    def get(self, *args, **kwargs):
        self.render("login.html")
    def post(self, *args, **kwargs):
        user = self.get_argument(‘user‘)
        pwd = self.get_argument(‘pwd‘)
        if user == "Mitsui" and pwd == ‘123‘:
            self.session[‘user‘] = user
            self.redirect(‘/index‘)
        else:
            self.render(‘login.html‘)


class IndexHandler(SessionHandler,RequestHandler):

    def get(self, *args, **kwargs):
        user = self.session[‘user‘]
        if user:
            self.write(‘歡迎登錄!‘)
        else:
            self.redirect(‘/login‘)


sett = {
    ‘template_path‘:‘views‘,
    #XSRF
    ‘xsrf_cookies‘:True,
}

application = tornado.web.Application([
    (r"/login",LoginHandler),
    (r"/index",IndexHandler),
],**sett)

if __name__ == ‘__main__‘:
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

  

配置文件settings:

#所選的session處理類
SESSION_ENGINE = "session_code.CacheSession"
#客戶端cookie中保存的key
SESSION_ID = "__session__id__"
#超時時間
EXPIRERS = 300

  



基於Tornado自定制仿Django的Session以及Form組件