forked from erp-dev/erp
157 lines
4.4 KiB
Markdown
157 lines
4.4 KiB
Markdown
# ViewSet 分页限制重构
|
||
|
||
## 概述
|
||
|
||
为了防止前端无限制地请求大量数据,对所有 ViewSet 实施统一的分页限制策略。
|
||
|
||
**日期**: 2025-12-25
|
||
|
||
## 改动内容
|
||
|
||
### 1. 新增基类 (`flower/viewsets.py`)
|
||
|
||
创建了三个带分页限制的 ViewSet 基类:
|
||
|
||
- **`LimitedLimitOffsetPagination`**: 自定义分页类
|
||
- `default_limit = 100`: 默认每页返回 100 条
|
||
- `max_limit = 100`: 最大每页返回 100 条
|
||
|
||
- **`LimitedModelViewSet`**: 继承自 `viewsets.ModelViewSet`
|
||
- 自动应用 `LimitedLimitOffsetPagination`
|
||
- 用于标准 CRUD 操作
|
||
|
||
- **`LimitedReadOnlyModelViewSet`**: 继承自 `viewsets.ReadOnlyModelViewSet`
|
||
- 自动应用 `LimitedLimitOffsetPagination`
|
||
- 用于只读场景
|
||
|
||
- **`LimitedGenericViewSet`**: 继承自 `viewsets.GenericViewSet`
|
||
- 自动应用 `LimitedLimitOffsetPagination`
|
||
- 用于自定义 actions
|
||
|
||
### 2. 更新所有 ViewSet
|
||
|
||
#### api_v1 模块
|
||
- ✅ `UploadFileViewSet` → 继承 `LimitedGenericViewSet`
|
||
- ✅ `StateParameterViewSet` → 继承 `LimitedModelViewSet`
|
||
- ✅ `ProductQuickViewSet` → 继承 `LimitedGenericViewSet`
|
||
- ✅ `StateViewSet` → 继承 `LimitedModelViewSet`
|
||
- ✅ `ProcessViewSet` → 继承 `LimitedModelViewSet`
|
||
- ✅ `BusinessObjectViewSet` → 继承 `LimitedModelViewSet`
|
||
- ✅ `PrintingOrderViewSet` → 继承 `LimitedModelViewSet`
|
||
- ✅ `PrintingJobViewSet` → 继承 `LimitedModelViewSet`
|
||
- ✅ `PlateOrderViewSet` → 继承 `LimitedModelViewSet`
|
||
- ✅ `MDYPlateOrderStagingViewSet` → 继承 `LimitedReadOnlyModelViewSet`
|
||
|
||
#### api_man 模块
|
||
- ✅ `BaseViewSet` → 继承 `LimitedModelViewSet`
|
||
- ✅ `QuickInputViewSet` → 继承 `LimitedModelViewSet`
|
||
- ✅ 所有继承自 `BaseViewSet` 的 ViewSet 自动获得分页限制:
|
||
- `ProductViewSet`
|
||
- `WareHouseViewSet`
|
||
- `ProductCategoryViewSet`
|
||
- `SupplierViewSet`
|
||
- `EmployeeViewSet`
|
||
- `EmployeeTypeViewSet`
|
||
- `CustomerViewSet`
|
||
- `VehicleTypeViewSet`
|
||
- `BankAccountViewSet`
|
||
- `DeviceInfoViewSet`
|
||
- `VehicleTransportRecordViewSet`
|
||
- `UserProfileViewSet`
|
||
|
||
#### api_v2 模块
|
||
- 暂无 ViewSet(使用 APIView)
|
||
|
||
### 3. 移除冗余配置
|
||
|
||
所有 ViewSet 中显式设置的 `pagination_class = LimitOffsetPagination` 已被移除,因为基类已经提供了更好的分页配置。
|
||
|
||
## 技术细节
|
||
|
||
### 分页行为
|
||
|
||
**之前**:
|
||
```python
|
||
class MyViewSet(viewsets.ModelViewSet):
|
||
pagination_class = LimitOffsetPagination # 无限制,可能导致性能问题
|
||
```
|
||
|
||
**之后**:
|
||
```python
|
||
class MyViewSet(LimitedModelViewSet):
|
||
# 自动继承分页限制,无需显式声明
|
||
pass
|
||
```
|
||
|
||
### API 请求示例
|
||
|
||
```bash
|
||
# 默认返回 100 条
|
||
GET /api/v1/printing-orders/
|
||
|
||
# 请求 50 条(正常)
|
||
GET /api/v1/printing-orders/?limit=50
|
||
|
||
# 请求 200 条 → 自动限制为 100 条
|
||
GET /api/v1/printing-orders/?limit=200
|
||
|
||
# 使用 offset 进行翻页
|
||
GET /api/v1/printing-orders/?limit=100&offset=100
|
||
```
|
||
|
||
### 响应格式
|
||
|
||
```json
|
||
{
|
||
"count": 1234,
|
||
"next": "http://example.com/api/v1/printing-orders/?limit=100&offset=100",
|
||
"previous": null,
|
||
"results": [...]
|
||
}
|
||
```
|
||
|
||
## 注意事项
|
||
|
||
1. **向后兼容**:所有现有 API 调用仍然有效
|
||
2. **自动限制**:即使前端请求 `limit=10000`,后端也只会返回最多 100 条
|
||
3. **新增 ViewSet**:今后创建新的 ViewSet 应继承 `flower.viewsets` 中的基类
|
||
4. **特殊需求**:如果某个 ViewSet 需要不同的限制,可以覆盖 `pagination_class`
|
||
|
||
## 文件清单
|
||
|
||
### 新增文件
|
||
- `flower/viewsets.py`
|
||
|
||
### 修改文件
|
||
- `api_v1/views/upload.py`
|
||
- `api_v1/views/parameters.py`
|
||
- `api_v1/views/products/views.py`
|
||
- `api_v1/views/stateflow/state.py`
|
||
- `api_v1/views/stateflow/process.py`
|
||
- `api_v1/views/stateflow/business_object.py`
|
||
- `api_v1/views/printing/views.py`
|
||
- `api_v1/views/mingdaoyun/plate_order_staging.py`
|
||
- `api_man/views.py`
|
||
|
||
## 测试建议
|
||
|
||
```bash
|
||
# 测试默认分页
|
||
curl "http://localhost:8000/api/v1/printing-orders/" -H "Authorization: Bearer TOKEN"
|
||
|
||
# 测试限制超出
|
||
curl "http://localhost:8000/api/v1/printing-orders/?limit=500" -H "Authorization: Bearer TOKEN"
|
||
|
||
# 验证返回的数据量不超过 100 条
|
||
```
|
||
|
||
## 下一步
|
||
|
||
如果需要调整限制数量(如改为 50 或 200),只需修改 `flower/viewsets.py` 中的 `LimitedLimitOffsetPagination` 类即可:
|
||
|
||
```python
|
||
class LimitedLimitOffsetPagination(LimitOffsetPagination):
|
||
default_limit = 50 # 修改这里
|
||
max_limit = 50 # 修改这里
|
||
```
|