【问题标题】:SoftDelete in DjangoDjango 中的软删除
【发布时间】:2019-02-21 03:28:31
【问题描述】:

问题陈述

我已经创建了一个基础模型:

class CreateUpdateDeleteModel(models.Model):
    from django.contrib.auth import get_user_model

    from django.utils.text import gettext_lazy as _

    from .managers import BakeryManager

    from drfaddons.datatypes import UnixTimestampField

    create_date = UnixTimestampField(_('Create Date'), auto_now_add=True)
    created_by = models.ForeignKey(get_user_model(), on_delete=models.PROTECT,
                                   related_name='%(app_label)s_%(class)s_creator')

    delete_date = models.DateTimeField(_('Delete Date'), null=True, blank=True)
    deleted_by = models.ForeignKey(get_user_model(), on_delete=models.PROTECT, null=True, blank=True,
                                   related_name='%(app_label)s_%(class)s_destroyer')

    update_date = models.DateTimeField(_('Date Modified'), auto_now=True)
    updated_by = models.ForeignKey(get_user_model(), on_delete=models.PROTECT, null=True, blank=True,
                                   related_name='%(app_label)s_%(class)s_editor')

    objects = BakeryManager()

    class Meta:
        abstract = True

我希望在我的系统中,所有元素都被软删除,即每当一个对象被删除时,它的行为应该如下:

  1. 行为与正常删除操作一样:如果 models.PROTECT 设置为 on_delete 的值,则引发错误,如果是 models.SET_NULL,则设置为 null 等等。
  2. 设置delete_date
  3. 永远不要在任何查询的任何地方(包括管理员)显示它。即使model.objects.all() 也不应该包含已删除的对象。

我该怎么做? 我正在考虑覆盖get_queryset(),这可能会解决problem 3。但是12 呢?

【问题讨论】:

    标签: django python-3.x django-models django-orm


    【解决方案1】:

    很奇怪的要求。

    第 1 点。不清楚。在哪里显示错误?

    第 2 点。删除是作为一种状态来管理的,而不是数据的隐藏。我建议您添加一个状态字段并使用更改状态的特殊功能来管理删除。可以覆盖delete,但要注意queryset中的delete不会调用Model.delete,而是直接运行SQL代码。

    说这是个坏主意。删除必须在那里,但只是没有使用。您可以轻松地删除 Django 管理员的删除表单,开发人员没有理由删除代码,除非他/她不负责任地使用 Django shell。 (数据库备份?)

    Point 3. 如果不想在 admin 中显示数据,只需在对象的 STATUS 为 DELETE 时覆盖 Admin ModelForm 以隐藏数据。操纵域以适应表示层是糟糕的设计。

    【讨论】:

    • 1.举个代码。道歉。 2. 明白了。 views 中的任何代码都将从foo.delete() 调用delete,其中foo 是类的对象。 3. 如何覆盖所有查询集以应用过滤器:.filter(delete_date=None)?我已根据您的评论更新了要点。谢谢
    • 第 2 点:我知道视图中的代码可以删除对象(以及应用程序的其他部分),但您应该编写测试以确保没有任何内容被删除。
    • 是的。工作相同。关于如何覆盖所有查询集的任何想法?
    • 我仍然认为您正在走一条非常艰难的道路,但是您可以覆盖对象管理器docs.djangoproject.com/en/2.1/topics/db/managers/#from-queryset
    • 确实如此。你说得对。最后,我能够说服客户这是他们不想拥有的东西。我将用你的回答结束这个问题。我将添加一些内容:如果我们甚至覆盖Manager 类中的get_queryset() 并将其设置为对象管理器,我们将实现结果,但是软删除的整个概念具有另一个线程:数据冗余。如果有人想重新创建该数据怎么办?因此,整个 Django 系统和 DBMS 结构受到威胁。
    猜你喜欢
    • 2018-10-17
    • 2013-02-04
    • 2014-09-09
    • 2020-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-09
    • 2013-12-28
    相关资源
    最近更新 更多