给 tornado 加装 session 轮子

tornado 是一个非常流行的 web framework,也是一个自带 IO 的 web server,而它作为 web server 采用的是 asynchronous IO 的网络模型,这是一种很高效的模型。网上有很多 tornado 与其他 web 框架的性能比较,其实,它们根本不是一个层次的东西,因为在所有的比较对象中,只有 tornado 同时具备 IO / web server / web framework,并且做到了极致。

开发 web 项目,我一般会首选 tornado 。喜欢 tornado,不是因为它全能,而是因为它简洁。简洁到什么程度呢?作为 web 框架,它连 session 都没有。但是,正是这种简洁,降低了学习成本,给用户提供了无限的开发空间。

为 tornado 增加 session 机制,基本思路就是从 tornado.web.RequestHandler 派生新类,重写 initialize() 方法。当类实例被构造函数创建后,会先运行该方法。我们定义 initialize() 方法读取名为 session_id 的 cookie,如果存在,则读取以 session_id 命名的 session 文件,取得 session 内容,否则,session 为空。

闲言少叙,直接上代码。这段代码在 py2 环境 tornado 2.x 以后的各种版本下都可运行。

# -*- coding: utf-8 -*-


# Tornado Session For py2
#---------------------------------------

# version 3.2 / Update: 2018-12-24
#
# 1. 重写get_current_user方法,读取session_id

# version 3.1 / Update: 2018-12-21
#
# 1. 以文件作为session的后端
# 2. 私有方法命名规范化

# version 3.0 / Update: 2018-12-19
#
# 1. 以cookie形式实现session
# 2. 用装饰器引入db
# 3. 类方法命名规范化(不兼容之前的版本)


import os, time
import hashlib
import json
import tornado.web


class SessionRH(tornado.web.RequestHandler):
    """为RequestHandler增加session机制"""
    
    def initialize(self):
        """初始化(构造函数完成之后)"""
        
        self._init_session()

    def _init_session(self):
        """session初始化"""
        
        self.session = dict()
        self.session_id = self.get_secure_cookie('session_id')
        if self.session_id:
            session_file = os.path.join(self.application.settings["session_path"], self.session_id)
            if os.path.isfile(session_file):
                with open(session_file, 'r') as fp:
                    self.session.update(json.loads(fp.read().strip()))
            
            if not self.session:
                self.session_id = None
                self.clear_cookie('session_id')

    def _save_session(self):
        """保存session"""
        
        try:
            expiry = self.application.settings["session_expiry"]
        except:
            expiry = 0
        
        if not expiry:
            expiry = None
        
        self.set_secure_cookie('session_id', self.session_id, expires_days=expiry)
        with open(os.path.join(self.application.settings["session_path"], self.session_id), 'w') as fp:
            fp.write(json.dumps(self.session))

    def create_session(self, **kwargs):
        """生成唯一的session_id及其它需要保存的数据项"""
        
        rand = os.urandom(16)
        now = time.time()
        self.session_id = hashlib.sha1("%s%s%s" %(rand, now, self.request.remote_ip)).hexdigest()
        self.session.update(kwargs)
        self.session.update({'last_active':str(now)})
        self._save_session()

    def destroy_session(self):
        """注销session"""
        
        session_file = os.path.join(self.application.settings["session_path"], self.session_id)
        if os.path.isfile(session_file):
            os.remove(session_file)
        
        self.session_id = None
        self.session = dict()
        self.clear_cookie('session_id')
    
    def append_session_item(self, **kwargs):
        """追加session项"""
        
        self.session.update(kwargs)
        self._save_session()

    def delete_session_item(self, name):
        """删除session项"""
        
        if name in self.session:
            self.session.pop(name)
            self._save_session()
    
    def get_current_user(self):
        """重写get_current_user方法,读取session_id"""
        
        return self.get_secure_cookie("session_id")

    @property
    def db(self):
        """用装饰器引入db(application.db)"""
        
        return self.application.db
        

if __name__ == '__main__':
    pass
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天元浪子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值