# 分页规范 ## 概述 统一使用 `pageNo`/`pageSize` 作为分页参数,Django `Paginator` 封装分页逻辑,返回标准分页结构。 :::tip 分页约定 - 前端传递 `pageNo`(页码,从 1 开始)和 `pageSize`(每页条数) - 后端返回 `{records, total, size, current, pages}` 结构 - 默认每页 10 条(`PAGE_SIZE = 10`) ::: ## 请求参数 | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `pageNo` | int | 否 | 1 | 页码,从 1 开始 | | `pageSize` | int | 否 | 10 | 每页条数 | ### 请求示例 ```bash # GET 请求 GET /example/page?pageNo=1&pageSize=10 # 带筛选条件 GET /example/page?pageNo=1&pageSize=10&name=案例&type=1&status=1 ``` ## 响应格式 ```json { "code": 0, "data": { "records": [ { "id": 1, "name": "案例名称", "type": 1, "status": 1, "sort": 1, "createUser": "admin", "createTime": "2026-01-01 10:00:00" } ], "total": 50, "size": 10, "current": 1, "pages": 5 }, "msg": "操作成功", "ok": true } ``` | 字段 | 类型 | 说明 | |------|------|------| | `records` | array | 当前页数据列表 | | `total` | int | 总记录数 | | `size` | int | 每页条数 | | `current` | int | 当前页码 | | `pages` | int | 总页数 | ## Service 实现 ### 分页查询方法 ```python from django.core.paginator import Paginator, PageNotAnInteger, InvalidPage, EmptyPage from constant.constants import PAGE_SIZE from utils import R def get_example_page(request): """查询案例分页数据""" try: # 获取分页参数 page_no = int(request.GET.get('pageNo', 1)) page_size = int(request.GET.get('pageSize', PAGE_SIZE)) # 构建基础查询(只查询未删除的记录) query = Example.objects.filter(is_delete=False) # 应用筛选条件 query = _apply_filters(query, request) # 按排序字段升序排列 query = query.order_by("sort") # 执行分页查询 paginator = Paginator(query, page_size) try: page_list = paginator.page(page_no) except (PageNotAnInteger, InvalidPage, EmptyPage): # 页码无效时默认返回第一页 page_list = paginator.page(1) page_no = 1 # 构建并返回分页数据 page_data = _build_page_data(page_list, paginator, page_no, page_size) return R.ok(data=page_data) except Exception as e: logging.error(f"查询案例分页数据异常: {str(e)}") return R.failed(msg="查询失败,请稍后重试") ``` ### 分页数据构建 ```python def _build_page_data(page_list, paginator, page_no, page_size): """构建分页返回数据""" records = [] for item in page_list: record = { 'id': item.id, 'name': item.name, 'type': item.type, 'status': item.status, 'sort': item.sort, 'createUser': item.create_user, 'createTime': format_datetime(item.create_time), 'updateUser': item.update_user, 'updateTime': format_datetime(item.update_time), } records.append(record) return { 'records': records, 'total': paginator.count, # 总记录数 'size': page_size, # 每页大小 'current': page_no, # 当前页码 'pages': paginator.num_pages # 总页数 } ``` ### 筛选条件应用 ```python def _apply_filters(queryset, request): """应用查询筛选条件""" # 名称模糊筛选 name = request.GET.get('name') if name: queryset = queryset.filter(name__contains=name) # 类型精确筛选 type = request.GET.get('type') if type: queryset = queryset.filter(type=type) # 状态精确筛选 status = request.GET.get('status') if status: queryset = queryset.filter(status=status) return queryset ``` :::tip 筛选字段说明 - 字符串字段使用 `__contains` 实现模糊查询(LIKE) - 整数字段直接使用 `=` 实现精确匹配 - 空值自动跳过,无需手动判断 ::: ## View 示例 ```python @method_decorator(check_login, name="get") class ExamplePageView(PermissionRequired, View): """案例分页数据查询视图""" permission_required = ("sys:example:page",) @operation_log(title="案例管理-查询分页列表", log_type=LogType.QUERY) def get(self, request): result = services.get_example_page(request) return result ``` :::tip 权限标识 分页接口权限标识格式:`sys:{模块名}:page` ::: ## 总结 分页规范统一使用 `pageNo`/`pageSize` 参数,通过 Django `Paginator` 处理分页逻辑。Service 层构建查询、应用筛选、执行分页、构建返回数据。响应使用 `R.ok(data=page_data)` 封装标准分页结构,前端可直接使用 `records`/`total`/`pages` 渲染列表和分页组件。