Skip to content

删除规范

概述

统一使用软删除机制,通过 is_delete 字段标记记录状态,不物理删除数据。删除操作分为单条删除和批量删除两种方式。

软删除约定

  • 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)

装饰器顺序

删除接口的装饰器顺序:@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)

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

_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)

返回值说明

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

小蚂蚁云团队 · 提供技术支持