Skip to content

分页规范

概述

统一使用 pageNo/pageSize 作为分页参数,BaseService.get_page() 封装分页逻辑,返回标准分页结构。

分页约定

  • 前端传递 pageNo(页码,从 1 开始)和 pageSize(每页条数)
  • 后端返回 {records, total, size, current, pages} 结构
  • 默认每页 10 条(PAGE_SIZE = 10

请求参数

参数类型必填默认值说明
pageNoint1页码,从 1 开始
pageSizeint10每页条数

请求示例

bash
# GET 请求
GET /api/v1/position/page?pageNo=1&pageSize=10

# 带筛选条件
GET /api/v1/position/page?pageNo=1&pageSize=10&name=开发&status=1

响应格式

json
{
    "code": 0,
    "data": {
        "records": [
            {
                "id": 1,
                "name": "开发工程师",
                "status": 1,
                "statusText": "在用",
                "sort": 1,
                "createTime": "2026-01-01 10:00:00"
            }
        ],
        "total": 50,
        "size": 10,
        "current": 1,
        "pages": 5
    },
    "msg": "操作成功",
    "ok": true
}
字段类型说明
recordsarray当前页数据列表
totalint总记录数
sizeint每页条数
currentint当前页码
pagesint总页数

BaseService 实现

get_page 方法

python
def get_page(self, request) -> R:
    """分页查询"""
    page, limit = parse_pagination(request)
    query = self._build_page_query(request)
    items, total = self.repo.paginate(page, limit, query)

    # 超页自动回退第 1 页
    if page > 1 and not items:
        page = 1
        items, total = self.repo.paginate(page, limit, query)

    result = [self._serialize(item) for item in items]
    return R.page(result, total, page, limit)

超页回退

当请求的页码超过总页数时(如删除数据后前端未刷新),自动回退到第 1 页,避免返回空数据。

分页查询构建

python
def _build_page_query(self, request):
    """组装分页查询:声明字段过滤 + 排序"""
    query = self.repo.filter()
    query = self._apply_page_filters(query, request)

    for field_name, direction in self.page_order_by:
        column = getattr(self.model, field_name)
        query = query.order_by(column.asc() if direction == 'asc' else column.desc())

    return query

字段过滤声明

python
class PositionService(BaseService[Position]):
    # 模糊查询字段:name LIKE %值%
    page_like_fields = ('name',)
    # 等值查询字段:status = 值
    page_eq_fields = ('status',)
    # 排序规则
    page_order_by = (('sort', 'asc'),)

:::tip 过滤字段说明
- `page_like_fields`:从 query_params 取同名参数,自动应用 `LIKE %%`,空值跳过
- `page_eq_fields`:从 query_params 取同名参数,自动应用 `=值`,空值跳过
- 两种字段均自动跳过 None/空字符串,无需手动判断
:::

## Repository 分页实现

```python
def paginate(self, page_no: int = 1, page_size: int = PAGE_SIZE, query=None):
    """分页查询,返回 (items, total)"""
    q = query if query is not None else self.db.query(self.model)
    q = q.filter(self._soft_col() == 0)  # 自动软删过滤
    total = q.count()
    items = q.limit(page_size).offset((page_no - 1) * page_size).all()
    return items, total

Endpoint 示例

python
@router.get('/page', summary='查询分页数据')
@permission_required("sys:position:page")
def page(request: Request):
    """获取岗位分页列表"""
    return position_service.get_page(request)

权限标识

分页接口权限标识格式:sys:{模块名}:page

自定义分页过滤

子类可覆盖 _apply_page_filters 添加固定过滤条件:

python
def _apply_page_filters(self, query, request):
    """添加固定过滤:只显示启用状态的数据"""
    query = super()._apply_page_filters(query, request)
    query = query.filter(self.model.status == 1)
    return query

总结

分页规范统一使用 pageNo/pageSize 参数,通过 BaseService.get_page() 自动处理分页逻辑。子类只需声明 page_like_fields/page_eq_fields/page_order_by 即可获得完整的分页能力。响应使用 R.page() 封装标准分页结构,前端可直接使用 records/total/pages 渲染列表和分页组件。

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