Skip to content

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 层处理。

小蚂蚁云团队 · 提供技术支持