Files
djangoadmin-wiki/DjangoAdmin_FastAPI_EleVue/zh/volume4/business/param.md
T
2026-09-12 23:12:15 +08:00

277 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
:::tip 参数管理
参数管理模块用于管理动态系统参数,与系统配置模块类似但更侧重于业务参数的灵活配置。支持按参数键查询、修改,无需重启服务即可生效。本模块是典型的「BaseService 简单模块」,通过声明差异点即可获得完整 CRUD 能力。
:::
## 模块结构
```
src/modules/param/
├── models.py # 参数模型
├── schemas.py # 表单验证
├── repository.py # 数据访问层
└── service.py # 业务逻辑层(继承 BaseService)
```
## 参数模型
```python
# src/modules/param/models.py
class Param(base_model, base_db):
"""参数模型类"""
__tablename__ = DB_PREFIX + "param"
__table_comment__ = "系统参数表"
# 参数名称
name = Column(String(100), nullable=False, index=True, comment="参数名称")
# 参数编码(唯一标识,用于业务代码中按编码取值)
code = Column(String(100), nullable=False, index=True, comment="参数编码")
# 参数值
value = Column(String(255), nullable=False, comment="参数值")
# 参数类型:0-系统 1-业务
type = Column(Integer, nullable=False, comment="参数类型:0-系统 1-业务")
# 参数状态:1-正常 2-禁用
status = Column(Integer, nullable=False, index=True, comment="参数状态:1-正常 2-禁用")
# 参数排序
sort = Column(Integer, nullable=False, comment="参数排序")
# 参数备注
note = Column(String(255), nullable=True, comment="参数备注")
```
其中 `id`、`create_user`、`create_time`、`update_user`、`update_time`、`is_delete` 由基类 `base_model` 自动提供。
## 表单验证
```python
class ParamForm(BaseForm):
name: str = Field(..., min_length=1, max_length=100, description="参数名称")
code: str = Field(..., min_length=1, max_length=100, description="参数编码")
value: str = Field(..., min_length=1, max_length=255, description="参数值")
type: int = Field(..., ge=0, le=1, description="参数类型:0-系统 1-业务")
status: int = Field(..., ge=1, le=2, description="参数状态:1-正常 2-禁用")
sort: int = Field(..., ge=0, le=99999, description="参数排序")
note: Optional[str] = Field(None, max_length=255, description="参数备注")
```
| 字段 | 必填 | 约束 | 说明 |
|:----|:----|:----|:----|
| `name` | 是 | `1~100 字符` | 参数名称,唯一 |
| `code` | 是 | `1~100 字符` | 参数编码,唯一,业务代码中按此取值 |
| `value` | 是 | `1~255 字符` | 参数值,字符串类型 |
| `type` | 是 | `0~1` | 0=系统参数,1=业务参数 |
| `status` | 是 | `1~2` | 1=正常,2=禁用(注意:非 0/1) |
| `sort` | 是 | `0~99999` | 排序号,值越大越靠前 |
| `note` | 否 | `max_length=255` | 备注说明 |
:::warning status 字段的取值范围
参数模块的 `status` 使用 `1=正常, 2=禁用`,与文章模块的 `0=正常, 1=下架` 不同。这是历史约定,开发时需注意区分。
:::
## Service 层设计
### 继承 BaseService
参数模块是典型的 BaseService 简单模块,只需声明差异点即可获得完整 CRUD 能力:
```python
class ParamService(BaseService[Param]):
"""参数业务服务类,继承基础服务获得通用 CRUD 能力"""
# ============ 必须声明 ============
repo = param_repo # 数据访问层实例
model = Param # 模型类
# ============ 分页差异点 ============
page_like_fields = ('name', 'code') # 模糊搜索字段
page_eq_fields = ('type', 'status') # 等值搜索字段
page_order_by = (('sort', 'asc'), ('id', 'desc')) # 排序规则
# ============ 唯一性校验 ============
unique_fields = {
'name': '参数名称不能重复',
'code': '参数编码不能重复'
}
# ============ 枚举显示名映射 ============
serialize_maps = {
'type': 'param_type', # 参数类型 → 数据字典
'status': 'param_status' # 参数状态 → 数据字典
}
# ============ 自定义方法 ============
def get_value_by_code(self, code: str, default: Optional[str] = None) -> Optional[str]:
"""根据参数编码获取参数值"""
param = self.repo.get_one(code=code, status=1)
return param.value if param else default
```
### 差异点详解
#### page_like_fields(模糊搜索)
声明后,BaseService 自动从 `request.query_params` 中取同名参数做 `LIKE %值%` 查询:
```python
# 声明 page_like_fields = ('name', 'code') 后
# 请求 GET /api/v1/param/page?name=默认&code=PASSWORD
# 自动生成:WHERE name LIKE '%默认%' AND code LIKE '%PASSWORD%'
```
#### page_eq_fields(等值搜索)
声明后,自动取同名参数做精确匹配:
```python
# 声明 page_eq_fields = ('type', 'status') 后
# 请求 GET /api/v1/param/page?type=0&status=1
# 自动生成:WHERE type = 0 AND status = 1
```
#### page_order_by(排序规则)
```python
# 声明 page_order_by = (('sort', 'asc'), ('id', 'desc'))
# 生成:ORDER BY sort ASC, id DESC
# 即排序号越小越靠前,同排序号时新记录在前
```
#### unique_fields(唯一性校验)
```python
# 声明 unique_fields = {'name': '参数名称不能重复', 'code': '参数编码不能重复'}
# 新增时:查询是否存在同名/同编码记录
# 编辑时:查询是否存在同名/同编码记录(排除自身 ID)
# 若重复:返回 R.failed('参数名称不能重复')
```
BaseService 内部自动调用 `repo.exists_by_field(field, value, exclude_id)` 实现,无需手写校验逻辑。
#### serialize_maps(枚举显示名映射)
```python
# 声明 serialize_maps = {'type': 'param_type', 'status': 'param_status'}
# 序列化时自动调用 get_dict_map('param_type') 获取字典映射
# 输出时自动补 data['type_name'] = '系统参数' / '业务参数'
# 输出时自动补 data['status_name'] = '正常' / '禁用'
```
分页列表和详情接口均自动输出枚举名称,前端可直接展示中文。
## 按编码取值
这是参数模块的核心自定义方法,供其他业务模块调用:
```python
param_service = ParamService()
# 获取参数值(存在且状态=正常时返回值,否则返回默认值)
default_pwd = param_service.get_value_by_code("USER_DEFAULT_PASSWORD", "123456")
upload_limit = param_service.get_value_by_code("UPLOAD_MAX_SIZE", "10")
maintenance = param_service.get_value_by_code("MAINTENANCE_MODE", "0")
```
### 实现原理
```python
def get_value_by_code(self, code: str, default: Optional[str] = None) -> Optional[str]:
param = self.repo.get_one(code=code, status=1) # 按编码查询,状态必须为正常
return param.value if param else default
```
- `repo.get_one(code=code, status=1)` 自动过滤软删除记录(`is_delete=0`)
- `status=1` 确保禁用的参数不会被读取
- 未找到时返回 `default` 值,避免调用方判空
:::tip 典型用法
在其他 service 中注入参数值,实现运行时可调的业务配置:
```python
from modules.param.service import param_service
def reset_password(user_id):
# 从参数表读取默认密码,无需硬编码
default_pwd = param_service.get_value_by_code("USER_DEFAULT_PASSWORD", "123456")
# ... 重置密码逻辑
```
:::
## Repository 层
```python
class ParamRepository(BaseRepository[Param]):
"""参数数据仓库,继承基础仓库获得通用 CRUD 能力"""
pass
param_repo = ParamRepository(Param)
```
参数模块无需自定义查询方法,BaseRepository 的通用方法已满足需求。
## API 接口
| 接口 | 方法 | 权限节点 | 说明 |
|:----|:----|:----|:----|
| `/api/v1/param/page` | GET | `sys:param:page` | 分页查询(支持 name/code 模糊搜索 + type/status 精确匹配) |
| `/api/v1/param/detail/{id}` | GET | `sys:param:detail` | 详情查询 |
| `/api/v1/param/add` | POST | `sys:param:add` | 新增参数(自动校验 name/code 唯一性) |
| `/api/v1/param/update` | PUT | `sys:param:update` | 编辑参数(自动校验 name/code 唯一性,排除自身) |
| `/api/v1/param/delete/{id}` | DELETE | `sys:param:delete` | 单条删除 |
| `/api/v1/param/batchDelete` | DELETE | `sys:param:batchDelete` | 批量删除 |
### 查询参数
分页接口支持以下查询参数(BaseService 自动处理):
| 参数 | 类型 | 说明 |
|:----|:----|:----|
| `pageNo` | int | 页码,默认 1 |
| `pageSize` | int | 每页条数,默认 10 |
| `name` | string | 参数名称,模糊搜索 |
| `code` | string | 参数编码,模糊搜索 |
| `type` | int | 参数类型,精确匹配(0=系统 1=业务) |
| `status` | int | 参数状态,精确匹配(1=正常 2=禁用) |
## 数据字典
参数模块使用以下数据字典(需在字典管理中配置):
| 字典编码 | 用途 | 字典项示例 |
|:----|:----|:----|
| `param_type` | 参数类型名称 | 0=系统参数, 1=业务参数 |
| `param_status` | 参数状态名称 | 1=正常, 2=禁用 |
BaseService 的 `serialize_maps` 声明后,分页列表和详情接口自动输出 `type_name` 和 `status_name` 字段。
## 与系统配置的区别
| 特性 | 参数管理(Param) | 系统配置(Config) |
|:----|:----|:----|
| 用途 | 单个系统参数 | 配置分组 + 配置项 |
| 结构 | 扁平(name+code+value) | 两级(config + config_item) |
| 典型场景 | 默认密码、功能开关、上传限制 | SMTP 配置、站点信息、第三方服务 |
| 取值方式 | `param_service.get_value_by_code()` | `config_service.get_value_by_key()` |
| Service 模式 | BaseService 子类 | BaseService 子类 |
## 开发要点
```
1. BaseService 子类:声明差异点即可,无需手写 CRUD 逻辑
2. 唯一性校验:unique_fields 声明后自动校验 name 和 code 唯一性
3. 枚举映射:serialize_maps 声明后自动输出 type_name 和 status_name
4. 按编码取值:get_value_by_code() 是核心方法,供其他模块调用
5. 状态值注意:status 使用 1=正常 2=禁用(非 0/1),与文章模块不同
6. 排序规则:page_order_by = (('sort', 'asc'), ('id', 'desc')),排序号越小越靠前
```
## 总结
参数管理模块是项目中典型的 BaseService 简单模块,核心特点:
```
1. 继承 BaseService:声明 repo/model/page_like_fields/page_eq_fields/unique_fields/serialize_maps 即可
2. 模糊 + 等值搜索:name/code 模糊搜索,type/status 等值搜索,BaseService 自动处理
3. 唯一性校验:name 和 code 双重唯一性,BaseService 自动校验
4. 枚举映射:type 和 status 自动映射为中文名称
5. 按编码取值:get_value_by_code() 供其他业务模块调用,实现运行时可调配置
6. 软删除 + 状态过滤:get_one 自动过滤已删除和已禁用的参数
```