248 lines
7.4 KiB
Markdown
248 lines
7.4 KiB
Markdown
下面是为提供的 `DataSourceProcessor` 类编写的 **Markdown 格式技术文档**,适用于项目中的开发者文档或 API 说明。
|
||
|
||
---
|
||
|
||
# `DataSourceProcessor` 技术文档
|
||
|
||
## 概述
|
||
|
||
`DataSourceProcessor` 是一个异步数据源处理器类,继承自 `BaseProcessor`,用于处理前端请求中与数据源相关的操作(如获取数据、分页、字段描述等)。它通过配置文件定义的数据结构,结合请求上下文动态生成响应内容,主要用于支持前端组件(如 DataGrid)的数据渲染和交互。
|
||
|
||
该类主要应用于后端服务中对 `.json` 配置文件的解析,并根据不同的 `action` 参数执行对应的数据处理逻辑。
|
||
|
||
---
|
||
|
||
## 模块依赖
|
||
|
||
```python
|
||
import codecs
|
||
import json
|
||
import aiofiles
|
||
from appPublic.jsonConfig import getConfig
|
||
from appPublic.dictObject import DictObject
|
||
from .baseProcessor import BaseProcessor
|
||
from .serverenv import ServerEnv
|
||
```
|
||
|
||
### 依赖说明:
|
||
|
||
| 模块 | 用途 |
|
||
|------|------|
|
||
| `aiofiles` | 异步读取文件内容,避免阻塞 I/O |
|
||
| `json` | 解析 JSON 格式的配置文件 |
|
||
| `getConfig` | 获取全局配置对象(如编码格式) |
|
||
| `DictObject` | 可选:用于将字典转换为对象访问形式 |
|
||
| `BaseProcessor` | 当前类的基类,提供通用处理接口 |
|
||
| `ServerEnv` | 提供服务器运行环境信息 |
|
||
|
||
---
|
||
|
||
## 类定义
|
||
|
||
```python
|
||
class DataSourceProcessor(BaseProcessor):
|
||
```
|
||
|
||
- **继承关系**:`BaseProcessor`
|
||
- **目的**:实现针对数据源(`ds`)类型资源的专用处理逻辑。
|
||
|
||
---
|
||
|
||
## 类方法
|
||
|
||
### `isMe(name) -> bool`
|
||
|
||
判断当前处理器是否适用于指定名称的资源。
|
||
|
||
#### 参数:
|
||
- `name` (`str`):资源类型标识符。
|
||
|
||
#### 返回值:
|
||
- `True` 当且仅当 `name == 'ds'`。
|
||
- 否则返回 `False`。
|
||
|
||
#### 示例:
|
||
```python
|
||
if DataSourceProcessor.isMe("ds"):
|
||
processor = DataSourceProcessor(...)
|
||
```
|
||
|
||
> ✅ 此方法为类方法,用于工厂模式下的处理器匹配。
|
||
|
||
---
|
||
|
||
## 实例初始化 `__init__(filename, k)`
|
||
|
||
构造函数,初始化处理器实例并设置可用操作集合。
|
||
|
||
#### 参数:
|
||
- `filename` (`str`):关联的配置文件路径。
|
||
- `k` (`str`):命名空间或键值,可能用于上下文隔离。
|
||
|
||
#### 初始化内容:
|
||
- 调用父类构造函数。
|
||
- 定义内置操作映射表 `self.actions`。
|
||
- 创建 `ServerEnv` 实例以获取服务器环境。
|
||
|
||
#### 支持的操作(`self.actions`):
|
||
|
||
| 动作名 | 对应方法 | 说明 |
|
||
|----------------|--------------------------|------|
|
||
| `getdata` | `getData()` | 获取原始数据(待实现) |
|
||
| `pagingdata` | `getPagingData()` | 获取分页数据(待实现) |
|
||
| `arguments` | `getArgumentsDesc()` | 获取参数描述(待实现) |
|
||
| `resultFields` | `getDataDesc()` | 获取结果字段结构(待实现) |
|
||
| `gridlist` | `getGridlist()` | 构造 DataGrid 所需结构(已实现) |
|
||
|
||
> ⚠️ 注意:前四个方法目前为空实现(`pass`),需子类或后续扩展实现具体逻辑。
|
||
|
||
---
|
||
|
||
## 核心方法
|
||
|
||
### `async getGridlist(dict_data, ns, request) -> dict`
|
||
|
||
生成前端 DataGrid 组件所需的配置结构,基于字段元数据自动组织列显示、冻结列、隐藏列等属性。
|
||
|
||
#### 参数:
|
||
- `dict_data` (`dict`):从配置文件加载的原始数据。
|
||
- `ns` (`dict`):命名空间参数,包含动作及其他上下文信息。
|
||
- `request` (`Request`):ASGI 请求对象,用于生成 URL。
|
||
|
||
#### 处理逻辑:
|
||
1. 调用 `getDataDesc()` 获取字段列表。
|
||
2. 分离出 `frozen=True` 的冻结列与非冻结列。
|
||
3. 根据 `listhide=True` 标记自动设置 `hide=True`。
|
||
4. 构建 DataGrid 配置对象:
|
||
- 设置分页大小为 50,禁用默认分页(由 buffer view 控制)
|
||
- 使用 `bufferview` 视图提升大数据量性能
|
||
- 添加查询 URL(指向 `?action=pagingdata`)
|
||
|
||
#### 返回值(示例):
|
||
```json
|
||
{
|
||
"__ctmpl__": "datagrid",
|
||
"data": {
|
||
"iconCls": "icon-search",
|
||
"url": "/api/ds/data.json?action=pagingdata",
|
||
"view": "bufferview",
|
||
"options": {
|
||
"pageSize": 50,
|
||
"pagination": false
|
||
},
|
||
"fields": [...], // 非冻结字段
|
||
"ffields": [...] // 冻结字段(可选)
|
||
}
|
||
}
|
||
```
|
||
|
||
> ✅ 已实现,可用于 EasyUI 或类似表格框架集成。
|
||
|
||
---
|
||
|
||
### `async path_call(request, path, params={}) -> Any`
|
||
|
||
异步读取指定路径的 JSON 配置文件,并根据请求参数调用对应的动作处理器。
|
||
|
||
#### 参数:
|
||
- `request` (`Request`):当前 HTTP 请求对象。
|
||
- `path` (`str`):JSON 配置文件路径。
|
||
- `params` (`dict`, optional):附加参数(未使用)。
|
||
|
||
#### 流程:
|
||
1. 读取文件内容(使用配置的编码,默认 UTF-8)。
|
||
2. 解析为 `dict_data`。
|
||
3. 获取运行时命名空间 `run_ns`。
|
||
4. 提取 `action` 参数(默认为 `'getdata'`)。
|
||
5. 查找并调用注册在 `self.actions` 中的处理函数。
|
||
|
||
#### 返回值:
|
||
- 调用对应 action 方法后的返回结果(通常是 `dict` 或 `list`)。
|
||
|
||
#### 异常处理建议(当前未实现):
|
||
- 文件不存在
|
||
- JSON 解析错误
|
||
- 不支持的 action
|
||
|
||
> 💡 建议后续增加异常捕获机制以提高健壮性。
|
||
|
||
---
|
||
|
||
### `async datahandle(request)`
|
||
|
||
统一入口方法,准备内容输出。**当前存在语法错误!**
|
||
|
||
#### 当前代码问题:
|
||
```python
|
||
self.content = await path_call(request, self.path)
|
||
```
|
||
❌ 错误原因:`path_call` 是实例方法,应通过 `self.path_call` 调用。
|
||
|
||
#### 修正版本:
|
||
```python
|
||
async def datahandle(self, request):
|
||
self.content = await self.path_call(request, self.path)
|
||
```
|
||
|
||
#### 说明:
|
||
- 将请求交由 `path_call` 处理,并将结果保存到 `self.content`。
|
||
- 通常用于后续响应序列化输出。
|
||
|
||
---
|
||
|
||
## 使用场景示例
|
||
|
||
假设有一个 `/static/ds/user_list.json` 文件,内容如下:
|
||
|
||
```json
|
||
{
|
||
"fields": [
|
||
{"name": "id", "title": "ID", "frozen": true},
|
||
{"name": "name", "title": "姓名", "listhide": false},
|
||
{"name": "email", "title": "邮箱", "listhide": true}
|
||
]
|
||
}
|
||
```
|
||
|
||
当访问:
|
||
|
||
```
|
||
GET /ds/user_list.json?action=gridlist
|
||
```
|
||
|
||
响应将自动生成兼容 DataGrid 的结构,其中:
|
||
- `id` 和 `name` 显示在主列区;
|
||
- `id` 在冻结列(`ffields`);
|
||
- `email` 因 `listhide=true` 被标记为 `hide=true`,不显示在列表中。
|
||
|
||
---
|
||
|
||
## 设计特点
|
||
|
||
| 特性 | 描述 |
|
||
|------|------|
|
||
| 🔧 可扩展性 | 新增动作只需添加到 `self.actions` 并实现方法 |
|
||
| 📦 配置驱动 | 数据结构完全由外部 `.json` 文件控制 |
|
||
| ⚡ 异步支持 | 使用 `aiofiles` 实现非阻塞文件读取 |
|
||
| 🖥️ 前端友好 | 输出结构适配常见 UI 框架(如 jQuery EasyUI) |
|
||
|
||
---
|
||
|
||
## 待改进事项(TODO)
|
||
|
||
1. ✅ **修复 `datahandle` 中的调用错误** → 应使用 `self.path_call`
|
||
2. 🛠️ 实现 `getData`, `getPagingData`, `getArgumentsDesc`, `getDataDesc` 具体逻辑
|
||
3. 🧯 增加异常处理(文件不存在、JSON 格式错误等)
|
||
4. 📐 支持更多前端控件模板(treegrid, combotree 等)
|
||
5. 🔐 添加权限校验钩子(可选)
|
||
|
||
---
|
||
|
||
## 总结
|
||
|
||
`DataSourceProcessor` 是一个轻量级、可扩展的数据源处理器,专为前后端分离架构设计,能够高效地将静态 JSON 配置转化为动态 API 响应,特别适合元数据驱动的管理系统开发。
|
||
|
||
---
|
||
|
||
📌 *文档版本:1.0*
|
||
📅 *最后更新:2025年4月5日* |