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

142 lines
4.5 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` 作为分页参数,通过 `BaseService.get_page()` → `Repository.page()` → `BaseRepository.find_page()` 链路完成分页查询,返回标准分页结构。
:::tip 分页约定
- 前端传递 `pageNo`(页码,从 1 开始)和 `pageSize`(每页条数)
- 后端返回分页数据字典,包含 `items` / `total` / `page` / `pageSize` / `pages` 等字段
- 默认每页 10 条(`PAGE_SIZE = 10`)
:::
## 分页流程
```
前端请求 GET /api/v1/position/page?pageNo=1&pageSize=10&name=工程师
↓
Router 层:R.ok(data=position.get_position_page(request.args))
↓
Service 层:BaseService.get_page(params)
↓
Repository 层:PositionRepository.page(params)
↓
BaseRepository.find_page(page, page_size, filters, like_filters, order_by)
↓
返回 (items, total, pages)
↓
build_page_data 构建分页数据字典
```
## Repository 层实现
```python
# src/modules/system/position/repository.py
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):
"""
岗位分页查询
Args:
params: 查询参数字典
- pageNo: 当前页码
- pageSize: 每页记录数
- name: 岗位名称(模糊匹配)
- status: 状态(精确匹配)
Returns:
tuple: (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',
)
```
## Service 层调用
```python
# src/common/base_service.py
from src.common.utils.model_utils import build_page_data
class BaseService:
@classmethod
def get_page(cls, params: dict) -> dict:
"""分页查询"""
page = int(params.get("pageNo", 1))
page_size = int(params.get("pageSize", PAGE_SIZE))
items, total, pages = cls.repository.page(params)
return build_page_data(
items, total, page, page_size, pages,
enrich=cls._enrich_page_records,
)
```
## Router 层调用
```python
# src/modules/system/position/router.py
@position_blue.route('/page', methods=["GET"])
@check_permission("sys:position:page")
def page():
"""查询岗位分页数据"""
return R.ok(data=position.get_position_page(request.args))
```
## 分页参数说明
| 参数 | 类型 | 说明 | 默认值 |
|:---|:---|:---|:---|
| `pageNo` | int | 当前页码(从 1 开始) | 1 |
| `pageSize` | int | 每页记录数 | 10 |
## 筛选参数说明
| 筛选类型 | Repository 参数 | 说明 | SQL 效果 |
|:---|:---|:---|:---|
| 等值匹配 | `filters={'status': 1}` | 精确匹配 | `WHERE status = 1` |
| 模糊匹配 | `like_filters={'name': '工程师'}` | 模糊匹配 | `WHERE name LIKE '%工程师%'` |
| 范围匹配 | `range_filters={'create_time': (start, end)}` | 范围匹配 | `WHERE create_time BETWEEN start AND end` |
:::tip 空值跳过
所有筛选条件自动跳过 `None` 和空字符串 `''`,前端不传某参数时不会影响查询结果。
:::
## 前端调用示例
```typescript
// ui/src/api/system/position/index.ts
export const getPositionPageApi = (params: any) => {
return http.request('get', '/position/page', { params });
};
// 使用
const { data } = await getPositionPageApi({ pageNo: 1, pageSize: 10, name: '工程师' });
// data.items = [...]
// data.total = 100
// data.pages = 10
```
## 开发要点
1. **分页参数统一使用 `pageNo` / `pageSize`**:前端和后端保持一致
2. **Repository 的 `page(params)` 方法必须实现**:Service 的 `get_page` 依赖此方法
3. **使用 `find_page` 构建查询**:传入 `filters` / `like_filters` / `range_filters` / `order_by`
4. **空值自动跳过**:前端不传的参数不会影响查询条件
5. **软删除自动过滤**:`find_page` 自动添加 `is_delete = 0` 条件
## 总结
分页查询通过 `Service.get_page(params)` → `Repository.page(params)` → `BaseRepository.find_page(...)` 链路完成。筛选条件通过 `filters`(等值)、`like_filters`(模糊)、`range_filters`(范围)三类参数传入,空值自动跳过,软删除自动过滤。