# 删除规范 ## 概述 统一使用软删除机制,通过 `is_delete` 字段标记记录状态,不物理删除数据。删除操作支持逗号分隔的多 ID 批量删除。 :::tip 软删除约定 - `is_delete = False`(0):正常记录(默认值) - `is_delete = True`(1):已删除记录 - 所有查询方法自动过滤 `is_delete=False`,业务层无需关心 ::: ## 软删除 vs 硬删除 | 维度 | 软删除 | 硬删除 | |------|--------|--------| | 实现方式 | 更新 `is_delete=True` | `DELETE FROM table` | | 数据可恢复 | ✅ 可恢复 | ❌ 不可恢复 | | 查询影响 | 需加 `is_delete=False` | 数据已不存在 | | 存储空间 | 占用(数据仍在表中) | 释放 | | 适用场景 | 业务数据(用户、订单等) | 日志、临时数据 | | 项目约定 | ✅ 统一使用 | ❌ 禁止使用 | ## BaseModel 公共字段 所有业务模型继承 `BaseModel`,自动包含 `is_delete` 字段: ```python # application/models.py class BaseModel(models.Model): """基础模型类""" class Meta: abstract = True id = models.AutoField(primary_key=True) create_user = models.CharField(max_length=50, null=True, blank=True) create_time = models.DateTimeField(auto_now_add=True) update_user = models.CharField(max_length=50, null=True, blank=True) update_time = models.DateTimeField(auto_now=True) is_delete = models.IntegerField(default=0, db_comment='是否删除:0-正常 1-已删除') ``` ## 删除接口 ### URL 格式 ``` DELETE /{module}/delete/{id} ``` 支持逗号分隔的多 ID 删除: ``` DELETE /example/delete/1,2,3 ``` ### View 示例 ```python @method_decorator(check_login, name="delete") class ExampleDeleteView(PermissionRequired, View): """删除案例视图""" permission_required = ('sys:example:delete',) @operation_log(title="案例管理-删除记录", log_type=LogType.DELETE) def delete(self, request, id): # 演示环境禁止操作 if DJANGO_DEMO: return R.failed("演示环境,暂无操作权限") result = services.delete_examples(id) return result ``` ## Service 实现 ```python def delete_examples(instance_ids): """删除案例(批量删除)""" if not instance_ids: return R.failed("记录ID不存在") try: # 解析ID列表 id_list = [int(id_str.strip()) for id_str in instance_ids.split(',') if id_str.strip()] if not id_list: return R.failed("无效的记录ID") # 批量更新删除标识(逻辑删除) updated_count = Example.objects.filter( id__in=id_list, is_delete=False ).update(is_delete=True) return R.ok(msg=f"本次共删除{updated_count}条数据") except ValueError: return R.failed("记录ID格式错误") except Exception as e: logging.error(f"删除案例异常,IDs: {instance_ids}, 错误: {str(e)}") return R.failed(msg="删除失败,请稍后重试") ``` :::tip 返回值说明 `delete` 方法返回实际软删除的条数。如果传入的 ID 中包含已删除或不存在的记录,返回值会小于入参数量。 ::: ## 删除流程 ``` 1. View 接收请求(id 参数,逗号分隔) ↓ 2. 演示模式检查(DJANGO_DEMO) ↓(拦截则返回 R.failed) 3. Service.delete_examples(id) ↓ 4. 解析 ID 列表(逗号分隔转 list) ↓ 5. ORM 批量更新 is_delete=True ↓ 6. 返回 R.ok(msg="本次共删除N条数据") ``` ## 查询过滤 所有查询方法必须过滤 `is_delete=False`: ```python # 分页查询 query = Example.objects.filter(is_delete=False) # 详情查询 instance = Example.objects.filter(is_delete=False, id=id).first() # 列表查询 queryset = Example.objects.filter(is_delete=False, status=1) # 带筛选条件的查询 query = Example.objects.filter(is_delete=False, name__contains=name) ``` :::warning 常见错误 忘记加 `is_delete=False` 是最常见的 bug,会导致已删除的数据重新出现在列表中。建议在代码审查时重点检查。 ::: ## 级联删除处理 当模块之间存在关联关系时,删除父记录需要同步处理子记录: ```python def delete_role(role_ids): """删除角色(同步清理关联数据)""" id_list = [int(id_str.strip()) for id_str in role_ids.split(',')] # 1. 软删除角色 updated_count = Role.objects.filter( id__in=id_list, is_delete=False ).update(is_delete=True) # 2. 同步软删除角色菜单关联 RoleMenu.objects.filter( role_id__in=id_list, is_delete=False ).update(is_delete=True) # 3. 同步软删除用户角色关联 UserRole.objects.filter( role_id__in=id_list, is_delete=False ).update(is_delete=True) return R.ok(msg=f"本次共删除{updated_count}条数据") ``` ## 数据恢复 软删除的数据可以通过恢复接口重新启用: ```python def restore_examples(instance_ids): """恢复已删除的案例""" id_list = [int(id_str.strip()) for id_str in instance_ids.split(',')] updated_count = Example.objects.filter( id__in=id_list, is_delete=True ).update(is_delete=False) return R.ok(msg=f"本次共恢复{updated_count}条数据") ``` :::tip 恢复场景 数据恢复通常用于: 1. 误删除后的数据恢复 2. 回收站功能 3. 数据审计 ::: ## 权限标识 | 操作 | 权限标识 | 说明 | |------|---------|------| | 删除 | `sys:{module}:delete` | 删除记录(支持批量) | ## 常见错误提示 | 提示 | 原因 | |------|------| | "记录ID不存在" | 入参为空 | | "无效的记录ID" | ID 格式错误或全部无效 | | "记录ID格式错误" | ID 包含非数字字符 | ## 最佳实践 ``` 1. 统一软删除:所有业务数据使用 is_delete 字段,禁止物理删除 2. 查询过滤:所有查询加 is_delete=False,避免遗漏 3. 级联处理:删除父记录时同步处理关联的子记录 4. 批量删除:支持逗号分隔的多 ID,提高操作效率 5. 错误提示:返回明确的错误信息,便于排查 6. 操作日志:删除操作记录操作日志,便于审计 ``` ## 总结 删除规范统一使用软删除(`is_delete` 标记),支持逗号分隔的多 ID 批量删除。Service 层解析 ID 列表后通过 ORM 批量更新 `is_delete=True`。所有查询方法自动过滤 `is_delete=False`,业务层无需关心软删除逻辑。级联删除时需同步处理关联数据,保证数据一致性。