在Django中覆盖QuerySet.delete() [英] Overriding QuerySet.delete() in Django
问题描述
我有一个Django模型,可以将应用程序的功能设置为核心。您不应该删除此模型。我试图强制这个应用程序范围。我已经禁用了admin中的删除功能,并且还禁用了模型上的delete方法,但是QuerySet有自己的delete方法。示例:
MyModel.objects.all()[0] .delete()#覆盖,不执行任何
MyModel.objects.all()。delete()#POOF!讽刺的是,Django文档说有这样的说法是为什么delete()是QuerySet的一个方法,不是经理:
这是一种安全机制,可以防止您意外请求Entry.objects.delete(),并删除所有条目。
如何包含 .all()
是一个安全机制至少说是值得怀疑的。相反,这有效地创建了一个不能通过常规方式关闭的后门(覆盖管理器)。
任何人都有一个线索,如何在某个东西作为核心覆盖此方法作为QuerySet没有猴子修补源?
解决方案您可以覆盖经理的
默认值 QuerySet
通过覆盖 Manager.get_query_set()
方法。
示例: h3>
class MyQuerySet(models.query.QuerySet):
def delete(self):
pass#你可以抛出一个异常
class NoDeleteManager(models.Manager):
def get_query_set(self):
return MyQuerySet(self.model,using = self._db)
class MyModel(models.Model)
field1 = ..
field2 = ..
objects = NoDeleteManager ()
现在, MyModel.objects.all()。delete()
将不执行任何操作。
有关更多信息:修改初始管理器QuerySets
I have a Django model that holds settings core to the function of an app. You should never delete this model. I'm trying to enforce this application-wide. I've disabled the delete function in the admin, and also disabled the delete method on the model, but QuerySet has it's own delete method. Example:
MyModel.objects.all()[0].delete() # Overridden, does nothing
MyModel.objects.all().delete() # POOF!
Ironically, the Django docs say has this to say about why delete() is a method on QuerySet and not Manager:
This is a safety mechanism to prevent you from accidentally requesting Entry.objects.delete(), and deleting all the entries.
How having to include .all()
is a "safety mechanism" is questionable to say the least. Instead, this effectively creates a backdoor that can't be closed by conventional means (overriding the manager).
Anyone have a clue how to override this method on something as core as QuerySet without monkey-patching the source?
解决方案 You can override a Manager's
default QuerySet
by overriding the Manager.get_query_set()
method.
Example:
class MyQuerySet(models.query.QuerySet):
def delete(self):
pass # you can throw an exception
class NoDeleteManager(models.Manager):
def get_query_set(self):
return MyQuerySet(self.model, using=self._db)
class MyModel(models.Model)
field1 = ..
field2 = ..
objects = NoDeleteManager()
Now, MyModel.objects.all().delete()
will do nothing.
For more informations: Modifying initial Manager QuerySets
这篇关于在Django中覆盖QuerySet.delete()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!