Files
djangoadmin-wiki/DjangoAdmin_Django_AntdVue/zh/volume7/pagination.md
T
2026-09-12 23:12:15 +08:00

187 lines
5.0 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.
# 分页规范
## 概述
统一使用 `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` 渲染列表和分页组件。