1

我正在使用以下设置在 Django 中实现软删除。我对幕后的 Django 不是很熟悉,所以我很感激任何关于我可能遇到的陷阱的反馈。我对 QuerySet 进行子类化特别不舒服。

基本思想是第一次调用deleteon aMyModel会改变当前的日期时间MyModeldate_deleted一秒钟delete实际上会删除该对象。(捕获 adelete需要两个覆盖,一个在对象上,一个在 上QuerySet,这可以绕过对象的delete方法。)由于默认管理器会隐藏已删除的对象,因此已删除的对象会消失,并且必须通过deleted_objects管理器显式请求。

使用此设置需要定义DeletionQuerySetDeletionManager添加date_deletedobjectsdeleted_objects到您的模型。

谢谢,

PS,忘了提到这种从默认管理器中过滤对象的方法是强烈反对的!

class DeletionQuerySet(models.query.QuerySet):

    def delete(self):
        prev_deleted = self.filter(date_deleted__isnull=False)
        prev_deleted.actual_delete()
        prev_undeleted = self.filter(date_deleted__isnull=True)
        prev_undeleted.update(date_deleted=datetime.datetime.now())

    def actual_delete(self):
        super(DeletionQuerySet, self).delete()

class DeletionManager(models.manager.Manager):

    # setting use_for_related_fields to True for a default manager ensures
    # that this manager will be used for chained lookups, a la double underscore,
    # and therefore that deleted Entities won't popup unexpectedly.
    use_for_related_fields = True

    def __init__(self, hide_deleted=False, hide_undeleted=False):
        super(DeletionManager, self).__init__()
        self.hide_deleted = hide_deleted
        self.hide_undeleted = hide_undeleted

    def get_query_set(self):
        qs = DeletionQuerySet(self.model)
        if self.hide_deleted:
            qs = qs.filter(date_deleted__isnull=True)
        if self.hide_undeleted:
            qs = qs.filter(date_deleted__isnull=False)
        return qs

class MyModel(models.Model):

    # Your fields here...
    date_deleted = models.DateTimeField(null=True)

    #the first manager defined in a Model will be the Model's default manager
    objects = DeletionManager(hide_deleted=True)
    deleted_objects = DeletionManager(hide_undeleted=True)

    def delete(self):
        if self.date_deleted is None:
            self.date_deleted = datetime.datetime.now()
            self.save()
        else:
            super(Agreement, self).delete()
4

1 回答 1

1

我认为任何具有当前使用、流行的技术的东西,都没有办法让问题域不可知的、通用的软删除。我认为它与历史/面向历史的数据库系统的联系比我们所使用的更多。我建议您不要规避 django 的删除(这是硬删除)。保持原样。

您最有可能在我们的系统中拥有的“删除”在 90% 的情况下是可视删除......

在这方面,请尝试为您的特定域问题找到删除的同义词,并从项目一开始就这样做。

因为抱怨 IsVisible、IsUnpublished(甚至 IsDeleted)会弄乱您的查询,所以他们抱怨您必须始终小心包含它们...

但这显然是对域问题的无知,如果域中有可以使不可见或未发布的对象 - 当然,当您查询要显示的所有对象的列表时,您应该从一开始,查询所有不可见且未发布的对象,因为这是以完整形式解决您的域问题的方式。

干杯。

于 2010-06-26T18:43:00.413 回答