在Django中重写QuerySet.delete()
我有一个Django模型,它将设置作为应用程序功能的核心。您不应该删除此模型。我正在尝试在整个应用程序中强制执行此操作。我在admin中禁用了delete函数,也在模型上禁用了delete方法,但是QuerySet有自己的delete方法。例如:在Django中重写QuerySet.delete(),django,Django,我有一个Django模型,它将设置作为应用程序功能的核心。您不应该删除此模型。我正在尝试在整个应用程序中强制执行此操作。我在admin中禁用了delete函数,也在模型上禁用了delete方法,但是QuerySet有自己的delete方法。例如: MyModel.objects.all()[0].delete() # Overridden, does nothing MyModel.objects.all().delete() # POOF! 具有讽刺意味的是,Django文档说,为什么de
MyModel.objects.all()[0].delete() # Overridden, does nothing
MyModel.objects.all().delete() # POOF!
具有讽刺意味的是,Django文档说,为什么delete()是QuerySet上的方法而不是Manager上的方法:
这是一种安全机制,可防止您意外请求Entry.objects.delete(),并删除所有条目
至少可以说,如何包含.all()
是一种“安全机制”是值得怀疑的。相反,这实际上创建了一个无法通过常规方式关闭的后门(覆盖管理器)
有人知道如何在像QuerySet这样的核心上重写此方法,而不必对源代码进行修补吗 通过覆盖
管理器.get\u query\u set()
方法,可以覆盖管理器的默认查询集
例子:
现在,MyModel.objects.all()
有关更多信息:mixin方法
使用@manji发布的类似配方
class DeactivateQuerySet(models.query.QuerySet):
'''
QuerySet whose delete() does not delete items, but instead marks the
rows as not active, and updates the timestamps
'''
def delete(self):
self.deactivate()
def deactivate(self):
deleted = now()
self.update(active=False, deleted=deleted)
def active(self):
return self.filter(active=True)
class DeactivateManager(models.Manager):
'''
Manager that returns a DeactivateQuerySet,
to prevent object deletion.
'''
def get_query_set(self):
return DeactivateQuerySet(self.model, using=self._db)
def active(self):
return self.get_query_set().active()
并创建一个mixin:
class DeactivateMixin(models.Model):
'''
abstract class for models whose rows should not be deleted but
items should be 'deactivated' instead.
note: needs to be the first abstract class for the default objects
manager to be replaced on the subclass.
'''
active = models.BooleanField(default=True, editable=False, db_index=True)
deleted = models.DateTimeField(default=None, editable=False, null=True)
objects = DeactivateManager()
class Meta:
abstract = True
其他有趣的东西
好吧,这对我来说是个大问题。我自己应该想到这一点,但谢谢你补充了我衰老的大脑的缺陷;)。django 1.6+中的方法被称为get\u queryset(self)
。您可以删除上面的管理器类,只需执行以下操作:objects=MyQuerySet.as\u manager()
从现在(Django 1.11)“get\u queryset”方法看起来像def get\u queryset(self):返回MyQuerySet(model=self.model,using=self.\u db,hints=self.\u hints)
class DeactivateMixin(models.Model):
'''
abstract class for models whose rows should not be deleted but
items should be 'deactivated' instead.
note: needs to be the first abstract class for the default objects
manager to be replaced on the subclass.
'''
active = models.BooleanField(default=True, editable=False, db_index=True)
deleted = models.DateTimeField(default=None, editable=False, null=True)
objects = DeactivateManager()
class Meta:
abstract = True