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

166 lines
4.4 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.
# 删除规范
## 概述
统一使用软删除机制,通过 `is_delete` 字段标记记录状态,不物理删除数据。删除操作分为单条删除和批量删除两种方式。
:::tip 软删除约定
- `is_delete = 0`:正常记录(默认值)
- `is_delete = 1`:已删除记录
- 所有查询方法自动过滤 `is_delete = 0`,业务层无需关心
:::
## 单条删除
### URL 格式
```
DELETE /api/v1/{module}/delete/{id}
```
支持逗号分隔的多 ID 删除:
```
DELETE /api/v1/position/delete/1,2,3
```
### Endpoint 示例
```python
@router.delete('/delete/{id}', summary='删除岗位')
@permission_required("sys:position:delete")
@check_demo
def delete(request: Request, id):
"""根据ID删除单个岗位"""
return position_service.delete(id)
```
:::tip 装饰器顺序
删除接口的装饰器顺序:`@router.delete` → `@permission_required` → `@check_demo`
:::
## 批量删除
### 请求格式
```
DELETE /api/v1/{module}/batchDelete
Content-Type: application/json
[1, 2, 3]
```
### Endpoint 示例
```python
@router.delete('/batchDelete', summary='批量删除岗位')
@permission_required("sys:position:batchDelete")
@check_demo
async def batch_delete(request: Request):
"""批量删除岗位"""
return await position_service.batch_delete(request)
```
:::warning async def 规则
批量删除端点必须为 `async def`,因为 `parse_batch_ids(request)` 需要异步读取请求体。
:::
## batch_delete_with_r 模式
### 原理
Repository 层的 `batch_delete` 只做数据原语(软删除 + 返回条数),Service 层通过 `BaseService.batch_delete_with_r()` 静态方法统一封装 R 响应。
```python
@staticmethod
def batch_delete_with_r(repo: BaseRepository, ids) -> R:
"""按逗号分隔ID软删除并返回标准R响应"""
id_list = parse_id_list(str(ids))
if not id_list:
return R.failed("记录ID不存在")
count = repo.batch_delete(ids)
if count != len(id_list):
return R.failed("记录不存在")
return R.ok(msg="本次共删除{0}条数据".format(count))
```
### 自定义 Service 复用
```python
class PositionService(BaseService[Position]):
def _before_delete(self, ids) -> Optional[str]:
"""删除前校验:存在用户引用时禁止删除"""
id_list = parse_id_list(str(ids))
if id_list and user_repo.filter(
User.position_id.in_(id_list), User.is_delete == 0
).first():
return "存在用户引用该岗位,请先调整用户岗位"
return None
```
:::tip _before_delete 钩子
- 返回 `None`:放行,继续删除
- 返回字符串:拦截,返回 `R.failed(字符串)`
- 用于检查子级引用、业务约束等
:::
## 删除流程
```
1. Endpoint 接收请求
↓
2. Service.delete(ids) 或 Service.batch_delete(request)
↓
3. _before_delete(ids) 钩子校验
↓(拦截则返回 R.failed)
4. batch_delete_with_r(repo, ids)
↓
5. repo.batch_delete(ids) 软删除
↓
6. 返回 R.ok(msg="本次共删除N条数据")
```
## Repository 层实现
```python
def batch_delete(self, ids_str) -> int:
"""按ID软删除,返回实际删除条数"""
id_list = parse_id_list(str(ids_str))
if not id_list:
return 0
records = self.db.query(self.model).filter(
self.model.id.in_(id_list), self._soft_col() == 0
).all()
for record in records:
setattr(record, self.soft_delete_col, 1)
return len(records)
```
:::tip 返回值说明
`batch_delete` 返回实际软删除的条数。如果传入的 ID 中包含已删除或不存在的记录,返回值会小于入参数量,此时 `batch_delete_with_r` 会返回失败提示。
:::
## 权限标识
| 操作 | 权限标识 | 说明 |
|------|---------|------|
| 单条删除 | `sys:{module}:delete` | 删除单条记录 |
| 批量删除 | `sys:{module}:batchDelete` | 批量删除记录 |
## 常见错误提示
| 提示 | 原因 |
|------|------|
| "记录ID不存在" | 入参为空或格式错误 |
| "记录不存在" | 部分或全部 ID 对应的记录已删除/不存在 |
| "存在用户引用该岗位" | _before_delete 钩子拦截 |
## 总结
删除规范统一使用软删除(`is_delete` 标记),支持单条删除(逗号分隔 ID)和批量删除(JSON 数组)。Repository 层做数据原语,Service 层通过 `batch_delete_with_r` 统一封装响应。自定义 Service 通过 `_before_delete` 钩子添加业务校验。批量删除端点必须为 `async def`。