Files
djangoadmin-wiki/DjangoAdmin_Flask_EleVue/zh/volume2/repository.md
T
2026-09-12 23:12:15 +08:00

197 lines
8.7 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.
# Repository 层
Repository 层是数据访问层,封装所有数据库查询操作。项目通过 `BaseRepository` 基类提供通用 CRUD 能力,子类只需声明 `model` 并按需实现 `page()` 和 `list_enabled()` 方法。
## 文件位置
```
src/modules/system/position/repository.py
```
## 完整代码
以岗位模块为例,`src/modules/system/position/repository.py` 完整内容:
```python
"""
岗位仓储模块
=============================================================
岗位数据访问层,继承 BaseRepository 获得通用 CRUD 能力。
"""
from src.common.base_repository import BaseRepository
from src.common.constants.common import PAGE_SIZE
from src.modules.system.position.models import Position
class PositionRepository(BaseRepository):
"""岗位数据仓储,提供岗位相关的数据库访问操作"""
model = Position
@classmethod
def page(cls, params: dict):
"""
岗位分页查询
支持按名称模糊搜索、按状态精确过滤,按 sort 字段升序排列。
Args:
params: 查询参数字典
- pageNo: 当前页码
- pageSize: 每页记录数
- name: 岗位名称(模糊匹配)
- status: 状态(精确匹配)
Returns:
tuple: (items, total, pages)
- items: 当前页数据列表
- total: 总记录数
- pages: 总页数
"""
return cls.find_page(
page=int(params.get('pageNo', 1)),
page_size=int(params.get('pageSize', PAGE_SIZE)),
filters={'status': params.get('status')},
like_filters={'name': params.get('name')},
order_by='sort',
)
@classmethod
def list_enabled(cls, params=None):
"""
查询启用的岗位列表
用于下拉选择场景,仅返回启用状态的岗位(status=1 为硬性条件,不可传参覆盖)。
支持与分页一致的条件筛选(name 模糊匹配)。
Args:
params: 查询参数字典,可包含 name 字段用于模糊搜索
Returns:
list: 启用状态的岗位实例列表,按 sort 升序排列
"""
params = params or {}
return cls.find_list(
filters={'status': 1},
like_filters={'name': params.get('name')},
order_by='sort',
)
```
## 代码解析
### 基类继承
```python
class PositionRepository(BaseRepository):
model = Position
```
`BaseRepository` 是基类,子类只需声明 `model` 即可获得通用 CRUD 能力。所有方法均为 `@classmethod`,无需创建实例。
### 必须实现的方法
| 方法 | 说明 | 何时需要 |
|:---|:---|:---|
| `page(params)` | 分页查询 | 所有模块(Service 的 `get_page` 依赖此方法) |
| `list_enabled(params)` | 无分页列表查询 | 需要下拉选择的模块(Service 的 `get_list` 依赖此方法) |
`page()` 和 `list_enabled()` 内部调用基类的 `find_page()` 和 `find_list()` 方法,传入筛选条件和排序规则。
### BaseRepository 提供的通用方法
| 方法 | 说明 |
|:---|:---|
| `get_by_id(obj_id)` | 按主键查询单条未删除记录 |
| `get_by_ids(ids)` | 按主键列表批量查询未删除记录 |
| `first_by(filters)` | 按等值条件查询单条记录 |
| `exists_by(filters, exclude_id)` | 检查是否存在未删除记录(唯一性校验) |
| `count_by(filters)` | 按等值条件统计未删除记录数 |
| `exists(obj_id)` | 检查未删除记录是否存在 |
| `count_children(parent_id)` | 统计子记录数(树形结构删除前校验) |
| `find_page(...)` | 统一分页查询(支持等值/模糊/范围过滤) |
| `find_list(...)` | 统一不分页查询 |
| `create(**kwargs)` | 创建并保存新实例 |
| `update_by_id(obj_id, data)` | 按主键更新字段 |
| `update_status(obj_id, status)` | 单独更新状态字段 |
| `delete_by_id(obj_id)` | 软删除单条记录 |
| `batch_delete(ids)` | 批量软删除 |
| `batch_restore(ids)` | 批量恢复已删除记录 |
### 何时需要自定义方法
大多数模块只需实现 `page()` 和 `list_enabled()`。当需要以下场景时,才在子类中添加自定义方法:
- **复杂联表查询**:如 User 需要关联 Dept、Role 查询
- **特殊聚合查询**:如统计、分组
- **非标准查询条件**:如区间查询、模糊 + 精确组合
示例(UserRepository):
```python
# src/modules/system/user/repository.py
class UserRepository(BaseRepository):
"""用户数据仓储"""
model = User
@classmethod
def page(cls, params: dict):
"""用户分页查询"""
return cls.find_page(
page=int(params.get('pageNo', 1)),
page_size=int(params.get('pageSize', PAGE_SIZE)),
like_filters={'realname': params.get('realname')},
filters={'gender': params.get('gender'), 'status': params.get('status')},
order_desc='id',
)
```
## Repository 与 Service 的关系
```
┌─────────────────────────────────────────────────────────────┐
│ Router 层 │
│ - 定义路由(Blueprint) │
│ - 权限校验(@check_permission) │
│ - 参数解析(parse_request_body) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Service 层 │
│ - 业务逻辑(BaseService 模板方法 + 钩子) │
│ - 表单校验(WTForms) │
│ - 存在性校验(Repository.exists_by) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Repository 层 │
│ - 数据库查询(classmethod) │
│ - CRUD 操作 │
│ - 软删除过滤(is_delete == 0) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Model 层 │
│ - 表结构定义(BaseModel + BaseDB) │
│ - 字段映射 │
└─────────────────────────────────────────────────────────────┘
```
## 开发要点
1. **所有方法均为 classmethod**:无需创建实例,直接通过类调用
2. **必须实现 `page(params)`**:Service 的 `get_page` 依赖此方法
3. **按需实现 `list_enabled(params)`**:需要下拉选择的模块实现此方法
4. **`find_page` / `find_list` 自动过滤软删除**:且跳过空值查询条件
5. **`exists_by(filters, exclude_id)` 用于唯一性校验**:支持排除自身 ID(更新时校验)
6. **Repository 层不做响应封装**:返回 SQLAlchemy 查询结果,由 Service 层处理响应
## 总结
Repository 层继承 `BaseRepository` 获得通用 CRUD 能力,所有方法均为 `classmethod`。子类只需声明 `model` 并实现 `page()` / `list_enabled()` 方法。`find_page` / `find_list` 自动过滤软删除且跳过空值条件,`exists_by` 用于唯一性校验。Repository 层不做响应封装,由 Service 层处理。