【问题标题】:Django remove bulk-deleteDjango删除批量删除
【发布时间】:2013-12-29 17:36:08
【问题描述】:

这是一个非常简单的问题:有什么好的方法可以禁止在整个 Django 项目中的所有模型上调用批量删除(当然是通过查询集)?

这样做的原因是,完全删除数据几乎总是一个糟糕的选择,而意外的批量删除可能是有害的。

【问题讨论】:

  • 我猜这将涉及子类化 QuerySet 并根据自己的喜好更改 delete 方法,子类化默认管理器并让它使用您的自定义查询集,子类化模型 - 创建一个抽象模型并让它使用您的自定义管理器,然后最终让您的所有模型子类化您的自定义抽象模型。
  • Elssar 的方法是我通常会做的。如果您正在处理现有代码库和/或不能确定所有模型都将从您的自定义抽象模型派生,另一种考虑的方法是根据需要修改 QuerySet 的删除方法。

标签: python django django-queryset


【解决方案1】:

就像 cmets 在您的第一篇文章中所说,您必须为这些元素中的每一个创建一个子类:

  1. 模型管理器
  2. 查询集类
  3. 基础模型

经过一番搜索,a great example can be found here,所有功劳归博客作者 Akshay Shah 所有。在查看代码之前,请注意:

但是,它不可避免地会导致数据损坏。 问题很简单:使用布尔值来存储删除状态使得无法在数据库中强制执行唯一性约束。

from django.db import models
from django.db.models.query import QuerySet


class SoftDeletionQuerySet(QuerySet):
    def delete(self):
        # Bulk delete bypasses individual objects' delete methods.
        return super(SoftDeletionQuerySet, self).update(alive=False)

    def hard_delete(self):
        return super(SoftDeletionQuerySet, self).delete()

    def alive(self):
        return self.filter(alive=True)

    def dead(self):
        return self.exclude(alive=True)


class SoftDeletionManager(models.Manager):
    def __init__(self, *args, **kwargs):
        self.alive_only = kwargs.pop('alive_only', True)
        super(SoftDeletionManager, self).__init__(*args, **kwargs)

    def get_queryset(self):
        if self.alive_only:
            return SoftDeletionQuerySet(self.model).filter(alive=True)
        return SoftDeletionQuerySet(self.model)

    def hard_delete(self):
        return self.get_queryset().hard_delete()


class SoftDeletionModel(models.Model):
    alive = models.BooleanField(default=True)

    objects = SoftDeletionManager()
    all_objects = SoftDeletionManager(alive_only=False)

    class Meta:
        abstract = True

    def delete(self):
        self.alive = False
        self.save()

    def hard_delete(self):
        super(SoftDeletionModel, self).delete()

基本上,它添加了一个alive 字段来检查该行是否已被删除,并在调用delete() 方法时更新它。
当然,这种方法只适用于可以操作代码库的项目。

【讨论】:

    【解决方案2】:

    有一些不错的现成应用程序可以恢复已删除的模型(如果您对此感兴趣),以下是我使用的:

    如果你真的想禁止批量删除,我会劝阻你不要使用这种方法:

    • 打破对应用程序行为的期望。如果我打电话给MyModel.objects.all().delete(),之后我希望桌子是空的。
    • 中断现有应用程序。

    如果你想这样做,请遵循评论中的建议:

    我猜这将涉及子类化 QuerySet 并根据自己的喜好更改删除方法,子类化默认管理器并让它使用您的自定义查询集,子类化模型 - 创建一个抽象模型并让它使用您的自定义管理器,然后最后让您的所有模型子类化您的自定义抽象模型。

    【讨论】:

      猜你喜欢
      • 2019-01-23
      • 2021-06-19
      • 2010-12-18
      • 2013-03-02
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      • 2019-08-09
      • 2016-10-24
      相关资源
      最近更新 更多