我正在尝试在django manager(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)
答案 0 :(得分:8)
当你打电话时:
SmsToken.objects.all().delete()
您正在调用查询集的删除方法。
但在SmsTokent.objects.last().delete()
上你正在调用实例的删除方法。
django 1.9 queryset delete
方法返回没有删除的项目。 REF
在Django 1.9中更改: 删除了描述已删除对象数的返回值。
但是在实例delete
方法上,Django已经知道只会删除一行。
另请注意,querset的删除方法和实例的删除方法不同。
delete()
[on a querset]
方法执行批量删除,并且不会在模型[instance method]
上调用任何delete()方法。但是,它会为所有已删除的对象(包括级联删除)发出pre_delete和post_delete信号。
因此,您不能依赖该方法的响应来检查删除是否正常。但就蟒蛇的哲学而言,请求宽恕而不是许可"。这意味着您可以依赖异常来查看删除是否以其应有的方式正常工作。 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.
注意:我正在捕获通用的Exception,因为我的try块中的唯一代码是delete
。如果您希望获得其他代码,则必须仅捕获特定的例外。
答案 1 :(得分:5)
我认为SoftDeletableModel
来自django-model-utils包裹?如果是这样,该模型的purpose将标记具有is_removed
字段的实例,而不是实际删除它们。因此,可以预期在模型实例上调用delete()
- 这是从last()
得到的 - 实际上不会删除任何内容。
SoftDeletableModel
provides objects
属性manager将其结果限制为未删除的对象,并覆盖delete()
以将对象标记为已删除实际上删除它们。
问题是您已将自己的经理定义为objects
,因此SoftDeletableModel
经理未被使用。您的自定义管理器实际上是从数据库中批量删除对象,这与执行软删除的目标相反。解决此问题的方法是让您的自定义管理器继承自SoftDeletableManagerMixin
:
class NexchangeManager(SoftDeletableManagerMixin, models.Manager):
# your custom code