|
|
from werobot.session import SessionStorage # WeRoBot 框架的会话存储基类
|
|
|
from werobot.utils import json_loads, json_dumps # WeRoBot 提供的 JSON 序列化/反序列化工具
|
|
|
|
|
|
from djangoblog.utils import cache # 项目中封装的缓存对象(如 Redis 或 Memcached)
|
|
|
|
|
|
|
|
|
class MemcacheStorage(SessionStorage):
|
|
|
"""
|
|
|
自定义的会话存储类,基于缓存系统(如 Redis/Memcached)实现 WeRoBot 微信机器人的会话管理。
|
|
|
用于在微信消息处理过程中持久化用户会话数据(如上下文、状态等)。
|
|
|
|
|
|
通过将用户 ID 作为键,会话数据作为值,存储在缓存中,实现跨请求的会话跟踪。
|
|
|
"""
|
|
|
|
|
|
def __init__(self, prefix='ws_'):
|
|
|
"""
|
|
|
初始化 MemcacheStorage 实例。
|
|
|
|
|
|
参数:
|
|
|
prefix (str): 缓存键的前缀,默认为 'ws_'(weobot session 的缩写),用于避免键名冲突。
|
|
|
|
|
|
功能:
|
|
|
- 设置键名前缀
|
|
|
- 绑定项目全局的缓存实例(cache)
|
|
|
"""
|
|
|
self.prefix = prefix # 设置键名前缀
|
|
|
self.cache = cache # 使用项目中已配置的缓存后端(如 Redis)
|
|
|
|
|
|
@property
|
|
|
def is_available(self):
|
|
|
"""
|
|
|
检查当前会话存储是否可用(即缓存系统是否正常工作)。
|
|
|
|
|
|
实现方式:
|
|
|
1. 尝试写入一个测试键值对('checkavaliable': '1')
|
|
|
2. 立即读取该键的值
|
|
|
3. 如果读取的值与写入的值一致,则认为存储可用
|
|
|
|
|
|
返回:
|
|
|
bool: True 表示缓存可用;False 表示不可用(如缓存服务宕机)
|
|
|
"""
|
|
|
value = "1"
|
|
|
self.set('checkavaliable', value=value) # 写入测试数据
|
|
|
return value == self.get('checkavaliable') # 验证能否正确读取
|
|
|
|
|
|
def key_name(self, s):
|
|
|
"""
|
|
|
为给定的会话 ID 生成带前缀的完整缓存键名。
|
|
|
|
|
|
参数:
|
|
|
s (str): 原始会话 ID(通常是微信用户的 OpenID)
|
|
|
|
|
|
返回:
|
|
|
str: 格式为 '{prefix}{s}' 的完整键名,用于避免命名冲突。
|
|
|
|
|
|
示例:
|
|
|
key_name('abc123') -> 'ws_abc123'
|
|
|
"""
|
|
|
return '{prefix}{s}'.format(prefix=self.prefix, s=s)
|
|
|
|
|
|
def get(self, id):
|
|
|
"""
|
|
|
根据会话 ID 从缓存中获取会话数据。
|
|
|
|
|
|
参数:
|
|
|
id (str): 会话 ID(如用户 OpenID)
|
|
|
|
|
|
返回:
|
|
|
dict: 会话数据的字典;如果缓存中不存在,则返回空字典 {}
|
|
|
|
|
|
流程:
|
|
|
1. 使用 key_name() 生成带前缀的键
|
|
|
2. 从缓存中获取 JSON 字符串
|
|
|
3. 使用 json_loads 将 JSON 字符串反序列化为 Python 字典
|
|
|
"""
|
|
|
id = self.key_name(id)
|
|
|
session_json = self.cache.get(id) or '{}' # 如果未找到,返回空 JSON 字符串
|
|
|
return json_loads(session_json)
|
|
|
|
|
|
def set(self, id, value):
|
|
|
"""
|
|
|
将会话数据存储到缓存中。
|
|
|
|
|
|
参数:
|
|
|
id (str): 会话 ID
|
|
|
value (dict): 要存储的会话数据(Python 字典)
|
|
|
|
|
|
流程:
|
|
|
1. 使用 key_name() 生成带前缀的键
|
|
|
2. 将字典序列化为 JSON 字符串
|
|
|
3. 存入缓存(使用默认过期时间)
|
|
|
"""
|
|
|
id = self.key_name(id)
|
|
|
self.cache.set(id, json_dumps(value)) # 序列化并存储
|
|
|
|
|
|
def delete(self, id):
|
|
|
"""
|
|
|
根据会话 ID 从缓存中删除会话数据。
|
|
|
|
|
|
参数:
|
|
|
id (str): 会话 ID
|
|
|
|
|
|
流程:
|
|
|
1. 使用 key_name() 生成带前缀的键
|
|
|
2. 调用缓存的 delete 方法删除该键
|
|
|
"""
|
|
|
id = self.key_name(id)
|
|
|
self.cache.delete(id) |