# 字典缓存工具 :::tip 说明 `src/common/utils/dict_util.py` 提供业务字典的缓存读取能力,从 Redis 缓存中获取字典数据,缓存未命中时从数据库加载。字典维护时自动失效缓存。 ::: ## 核心接口 ### get_dict_data — 获取字典下拉数据 ```python from common.utils.dict_util import get_dict_data # 获取字典编码对应的下拉选项列表 options = get_dict_data("link_type") # 返回: [{"label": "友情链接", "value": "1"}, {"label": "合作伙伴", "value": "2"}] ``` ### get_dict_label — 获取字典项标签 ```python from common.utils.dict_util import get_dict_label # 根据字典编码和值获取显示标签 label = get_dict_label("link_type", "1") # 返回: "友情链接" ``` ### get_dict_map — 获取字典值→标签映射 ```python from common.utils.dict_util import get_dict_map # 获取字典编码的值→标签映射字典 mapping = get_dict_map("link_type") # 返回: {"1": "友情链接", "2": "合作伙伴"} ``` ## 缓存策略 ``` 1. 读取 Redis 缓存: dict:{code} ├─ 命中 → 直接返回 └─ 未命中 → 从 DB 查询 → 写入 Redis → 返回 2. 字典维护(增删改)→ 删除 Redis 缓存 → 下次读取时自动重建 ``` ### Redis Key 设计 | Key | 说明 | TTL | |:----|:-----|:----| | `dict:{code}` | 字典编码对应的选项列表 | 不过期(主动失效) | | `dict:version` | 字典版本号(缓存失效触发器) | 不过期 | ### 缓存失效 字典数据变更时,通过递增版本号使所有缓存失效: ```python def invalidate_dict_cache(): """字典数据变更时调用,递增版本号使缓存失效。""" redis = get_redis() redis.incr("dict:version") ``` ## 在 BaseService 中使用 通过 `serialize_maps` 声明字段→字典编码映射,序列化时自动转换: ```python class LinkService(BaseService): serialize_maps = { "type": "link_type", # type 字段按 link_type 字典解析 "form": "link_form", # form 字段按 link_form 字典解析 } ``` 序列化时自动将 `type="1"` 转换为 `type_label="友情链接"`。 ## 与字典模块的关系 | 模块 | 职责 | |:-----|:-----| | `modules/dictionary/` | 字典数据的 CRUD 维护 | | `common/utils/dict_util.py` | 字典数据的缓存读取 | 字典维护接口在增删改时自动调用 `invalidate_dict_cache()`,读取端无需关心缓存一致性。 ## 使用场景 ### 场景一:Service 序列化自动转换 通过 `serialize_maps` 声明字段→字典编码映射,列表/详情序列化时自动追加 `xxxText` 字段: ```python class LinkService(BaseService): serialize_maps = { "type": "link_type", # type → typeText "form": "link_form", # form → formText } ``` 序列化结果: ```json { "id": 1, "name": "小蚂蚁云", "type": "1", "typeText": "友情链接", "form": "2", "formText": "后台添加" } ``` ### 场景二:Handler 下拉接口 ```python class DictDataHandler(BaseHandler): async def get(self, code): """GET /api/v1/dict/data/{code}""" items = get_dict_data(code) return R.ok(self, data=items) ``` 前端调用: ```javascript const res = await request({ url: '/api/v1/dict/data/link_type' }); // res.data: [{"label": "友情链接", "value": "1"}, {"label": "合作伙伴", "value": "2"}] ``` ### 场景三:后端业务校验 ```python def _before_add(self, handler, data): """新增前校验:字典值是否合法""" valid_types = get_dict_map("link_type") if str(data.get("type")) not in valid_types: raise ValidationError("链接类型不合法") ``` ### 场景四:导出 Excel 翻译 ```python def get_export_data(self, handler): items = self.repo.all() type_map = get_dict_map("link_type") result = [] for item in items: result.append({ "name": item.name, "type": type_map.get(str(item.type), "未知"), # 数字→中文 }) return result ``` ## 总结 字典缓存工具提供 `get_dict_data`、`get_dict_label`、`get_dict_map` 三个核心接口,基于 Redis 缓存实现高性能读取。字典维护时通过版本号机制自动失效缓存,保证数据一致性。广泛用于 Service 序列化、下拉接口、业务校验、导出翻译等场景。