0

0

Django 软删除实现指南:告别硬删除,拥抱数据安全

碧海醫心

碧海醫心

发布时间:2025-09-13 10:35:01

|

529人浏览过

|

来源于php中文网

原创

Django 软删除实现指南:告别硬删除,拥抱数据安全

本文深入探讨了在 Django 中实现数据软删除的策略与实践,旨在帮助开发者避免默认的硬删除行为。我们将介绍如何利用第三方库 django-safedelete 或自定义管理器来优雅地实现软删除,从而保护数据完整性,并提供详细的实现步骤、代码示例及注意事项,确保您的 Django 应用能够灵活处理数据生命周期。

为什么需要软删除?

在 django orm 中,模型的 delete() 方法默认执行的是硬删除(hard delete),即直接从数据库中移除数据。然而,在许多实际应用场景中,直接删除数据可能会带来一系列问题,例如:

  • 数据丢失风险: 误操作导致的数据无法恢复。
  • 审计追踪困难: 无法追踪数据的历史状态或删除操作。
  • 关联数据完整性: 复杂的关联关系可能因硬删除而破坏。
  • 业务需求: 某些业务逻辑要求数据在逻辑上被标记为“已删除”,但仍需保留以供查询或恢复(例如“回收站”功能)。

为了解决这些问题,软删除(Soft Delete)应运而生。软删除通过在模型中添加一个标记字段(如 is_deleted 或 deleted_at),在执行删除操作时仅更新此字段的状态,而不是真正删除数据库记录。

实现软删除的两种主要方法

在 Django 中实现软删除,主要有两种途径:使用第三方库或自定义模型管理器。

方法一:使用 django-safedelete (推荐)

django-safedelete 是一个功能强大且易于集成的第三方库,它为 Django 模型提供了全面的软删除功能,包括多种删除策略和方便的查询接口。

1. 安装与配置

首先,通过 pip 安装 django-safedelete:

pip install django-safedelete

然后,将其添加到 Django 项目的 INSTALLED_APPS 中:

# settings.py
INSTALLED_APPS = [
    # ...
    'safedelete',
    # ...
]

2. 模型集成

要使模型支持软删除,只需让其继承 safedelete.models.SafeDeleteModel 而不是 django.db.models.Model,并定义 _safedelete_policy 属性来指定删除策略。

# myapp/models.py
from django.db import models
from safedelete.models import SafeDeleteModel, SOFT_DELETE_CASCADE

class EmpModel(SafeDeleteModel):
    # 定义软删除策略
    # SOFT_DELETE_CASCADE: 软删除时,级联软删除关联对象
    # HARD_DELETE: 执行硬删除
    # NO_DELETE: 禁止删除
    # SOFT_DELETE: 仅软删除当前对象
    _safedelete_policy = SOFT_DELETE_CASCADE

    name = models.CharField(max_length=100)
    email = models.EmailField(unique=True)
    # ... 其他字段

    def __str__(self):
        return self.name

完成模型修改后,记得执行数据库迁移:

python manage.py makemigrations
python manage.py migrate

3. 视图层操作

集成 django-safedelete 后,您现有的 delete() 方法调用将自动执行软删除。

# myapp/views.py
from django.shortcuts import render, redirect, get_object_or_404
from .models import EmpModel

def Delemp(request, id):
    # 获取要删除的员工对象
    delemployee = get_object_or_404(EmpModel, id=id)

    # 调用 delete() 方法,现在它将执行软删除
    delemployee.delete()

    # 获取所有未被软删除的员工数据
    showdata = EmpModel.objects.all()
    return render(request, "Index.html", {"data": showdata})

def RestoreEmp(request, id):
    # 获取被软删除的员工对象
    # all_objects 管理器可以查询所有对象,包括已软删除的
    employee_to_restore = get_object_or_404(EmpModel.all_objects, id=id)

    # 恢复对象
    employee_to_restore.undelete()

    showdata = EmpModel.objects.all()
    return render(request, "Index.html", {"data": showdata})

4. 查询软删除数据

阿里妈妈·创意中心
阿里妈妈·创意中心

阿里妈妈营销创意中心

下载

django-safedelete 提供了额外的管理器来方便地查询不同状态的数据:

  • EmpModel.objects.all(): 默认只返回未被软删除(即活跃)的对象。
  • EmpModel.all_objects.all(): 返回所有对象,包括活跃的和已软删除的。
  • EmpModel.deleted_objects.all(): 只返回已被软删除的对象。

5. 执行硬删除

如果需要强制执行硬删除,即使模型配置了软删除策略,也可以使用 hard_delete() 方法:

delemployee.hard_delete() # 这将从数据库中永久删除记录

方法二:自定义模型管理器

如果您不想引入第三方库,或者需要更细粒度的控制,可以手动实现软删除逻辑。

1. 修改模型

在模型中添加一个布尔字段 is_deleted(或 deleted_at datetime 字段),并重写 delete 方法。

# myapp/models.py
from django.db import models

class SoftDeleteManager(models.Manager):
    def get_queryset(self):
        # 默认只返回未被删除的对象
        return super().get_queryset().filter(is_deleted=False)

    def all_objects(self):
        # 返回所有对象,包括已删除的
        return super().get_queryset()

    def deleted_objects(self):
        # 返回所有已删除的对象
        return super().get_queryset().filter(is_deleted=True)

class EmpModel(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(unique=True)
    is_deleted = models.BooleanField(default=False) # 软删除标记

    objects = SoftDeleteManager() # 使用自定义管理器

    def delete(self, *args, **kwargs):
        # 重写 delete 方法,执行软删除
        self.is_deleted = True
        self.save()

    def undelete(self, *args, **kwargs):
        # 恢复软删除对象
        self.is_deleted = False
        self.save()

    def hard_delete(self, *args, **kwargs):
        # 执行硬删除
        super().delete(*args, **kwargs)

    def __str__(self):
        return self.name

同样,修改模型后需要进行数据库迁移。

2. 视图层操作

视图层的操作与 django-safedelete 类似,但需要手动调用 undelete() 和 hard_delete() 方法。

# myapp/views.py
from django.shortcuts import render, redirect, get_object_or_404
from .models import EmpModel

def Delemp(request, id):
    delemployee = get_object_or_404(EmpModel, id=id)
    delemployee.delete() # 调用重写的 delete 方法,执行软删除
    showdata = EmpModel.objects.all()
    return render(request, "Index.html", {"data": showdata})

def RestoreEmp(request, id):
    # 使用 all_objects 管理器查询已删除的对象
    employee_to_restore = get_object_or_404(EmpModel.all_objects, id=id)
    employee_to_restore.undelete() # 恢复对象
    showdata = EmpModel.objects.all()
    return render(request, "Index.html", {"data": showdata})

def HardDeleteEmp(request, id):
    # 如果需要彻底删除,调用 hard_delete
    employee_to_hard_delete = get_object_or_404(EmpModel.all_objects, id=id)
    employee_to_hard_delete.hard_delete()
    showdata = EmpModel.objects.all()
    return render(request, "Index.html", {"data": showdata})

关键注意事项

  1. 性能影响: 软删除会在数据库中保留更多数据,可能增加数据库的存储空间。同时,查询时额外的 WHERE is_deleted = FALSE 条件可能会对查询性能产生轻微影响,但通常可以通过合理建立索引来缓解。
  2. 唯一性约束: 如果模型字段有 unique=True 约束,软删除的对象仍然会占用该唯一值。如果需要允许软删除的对象与新对象使用相同的唯一值(例如,用户账号被删除后,新用户可以注册相同的邮箱),您可能需要调整唯一性约束,例如在 is_deleted=True 时允许重复,或使用 UniqueConstraint 结合条件表达式。
  3. 级联删除: 在处理关联模型时,软删除的级联行为需要特别注意。django-safedelete 的 SOFT_DELETE_CASCADE 策略可以很好地处理这一点。如果自定义实现,则需要在重写的 delete 方法中手动处理关联对象的软删除逻辑。
  4. UI/UX 考虑:前端界面中,需要明确区分活跃数据和已软删除数据(例如,提供“回收站”或“已归档”视图),并提供相应的恢复或永久删除操作。
  5. 数据清理: 即使是软删除,有时也需要定期清理那些长时间处于软删除状态的数据,以释放存储空间或满足合规性要求。

总结

在 Django 应用中实现软删除是维护数据完整性和提升业务灵活性的重要实践。无论是选择功能丰富、易于集成的 django-safedelete 库,还是通过自定义管理器实现更精细的控制,理解其核心原理和注意事项都至关重要。通过合理运用软删除机制,您可以有效地管理数据生命周期,为用户提供更安全、更可靠的应用体验。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
pip安装使用方法
pip安装使用方法

安装步骤:1、确保Python已经正确安装在您的计算机上;2、下载“get-pip.py”脚本;3、按下Win + R键,然后输入cmd并按下Enter键来打开命令行窗口;4、在命令行窗口中,使用cd命令切换到“get-pip.py”所在的目录;5、执行安装命令;6、验证安装结果即可。大家可以访问本专题下的文章,了解pip安装使用方法的更多内容。

339

2023.10.09

更新pip版本
更新pip版本

更新pip版本方法有使用pip自身更新、使用操作系统自带的包管理工具、使用python包管理工具、手动安装最新版本。想了解更多相关的内容,请阅读专题下面的文章。

412

2024.12.20

pip设置清华源
pip设置清华源

设置方法:1、打开终端或命令提示符窗口;2、运行“touch ~/.pip/pip.conf”命令创建一个名为pip的配置文件;3、打开pip.conf文件,然后添加“[global];index-url = https://pypi.tuna.tsinghua.edu.cn/simple”内容,这将把pip的镜像源设置为清华大学的镜像源;4、保存并关闭文件即可。

761

2024.12.23

python升级pip
python升级pip

本专题整合了python升级pip相关教程,阅读下面的文章了解更多详细内容。

349

2025.07.23

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1076

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

169

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1321

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

16

2026.01.19

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

6

2026.01.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.3万人学习

Django 教程
Django 教程

共28课时 | 3.6万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号