我正在尝试重写 django 管理器 (models.Manager) 上的 get_by_natural_key 方法。添加模型 (NexchangeModel) 后,我可以删除所有 () 对象,但不能删除单个对象。
可以:
SmsToken.objects.all().delete()
不能:
SmsTokent.objects.last().delete()
代码:
from django.db import models
from core.common.models import SoftDeletableModel, TimeStampedModel, UniqueFieldMixin
class NexchangeManager(models.Manager):
def get_by_natural_key(self, param):
qs = self.get_queryset()
lookup = {qs.model.NATURAL_KEY: param}
return self.get(**lookup)
class NexchangeModel(models.Model):
class Meta:
abstract = True
objects = NexchangeManager()
class SmsToken(NexchangeModel, SoftDeletableModel, UniqueFieldMixin):
sms_token = models.CharField(
max_length=4, blank=True)
user = models.ForeignKey(User, related_name='sms_token')
send_count = models.IntegerField(default=0)
最佳答案
当您打电话时:
SmsToken.objects.all().delete()
您正在调用查询集的 delete 方法。
但是在 SmsTokent.objects.last().delete()
上,您正在调用实例的 delete 方法。
在 django 1.9 之后,queryset delete
方法返回没有删除的项目。 REF
Changed in Django 1.9: The return value describing the number of objects deleted was added.
但是在 delete
实例中,Django 方法已经知道只会删除一行。
还要注意,querset的delete方法和instance的delete方法是不一样的。
The delete()
[on a querset]
method does a bulk delete and does not call any delete() methods on your models[instance method]
. It does, however, emit the pre_delete and post_delete signals for all deleted objects (including cascaded deletions).
因此您不能依赖方法的响应来检查删除是否正常进行。但就 python 的哲学而言,“请求宽恕而不是许可”。这意味着您可以依靠异常来查看删除是否按应有的方式正常工作。 Django 的 ORM 将引发适当的异常并在出现任何故障时进行适当的回滚。
所以你可以这样做:
try:
instance.delete()/querset.delete()
except Exception as e:
# some code to notify failure / raise to propagate it
# you can avoid this try..except if you want to propagate exceptions as well.
注意:我正在捕获一般异常,因为我的 try block 中的唯一代码是 delete
。如果您希望有一些其他代码,那么您必须只捕获特定的异常。
关于python - 重写model.Manager方法后Django无法删除单个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42828497/