签入版本
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
# 字典缓存工具
|
||||
|
||||
:::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 序列化、下拉接口、业务校验、导出翻译等场景。
|
||||
Reference in New Issue
Block a user