在Django中使用pre_save时取消保存模型

28 投票
3 回答
17421 浏览
提问于 2025-04-18 08:01

我有一个模型:

class A(models.Model):
    number = models.IntegerField()

但是当我调用 A.save() 的时候,我想确保这个数字是一个质数(或者满足其他条件),如果不满足这些条件,就应该取消保存操作。

那么我该如何在预保存信号接收器中取消保存操作呢?

@receiver(pre_save, sender=A)
def save_only_for_prime_number(sender, instance, *args, **kwargs):
    # how can I cancel the save here?

3 个回答

5

如果数据总是来自一个表单,并且你有一个简单的方法来判断是否应该保存数据,那就可以使用一个叫做验证器的东西。不过要注意,验证器不会在后台的save()调用时被触发。如果你想让这些调用也受到保护,可以创建一个自定义字段,比如说class PrimeNumberField(models.SmallIntegerField)。如果你运行测试并在这个自定义字段的to_python()方法中抛出一个异常,这样就会阻止保存操作。你还可以通过重写字段、表单或模型上的一些其他方法来对特定字段的验证进行干预。

15

我不太确定仅仅通过 pre_save 信号能否取消保存。不过,你可以通过重写 save 方法轻松实现这个功能:

def save(self):
    if some_condition:
        super(A, self).save()
    else:
       return   # cancel the save

正如 @Raptor 提到的,调用者并不知道保存是否成功。如果这是你的需求,可以看看 另一个答案,它强制调用者处理“未保存”的情况。

28

请查看我另一个回答: https://stackoverflow.com/a/32431937/2544762

这种情况是正常的,如果我们只是想阻止保存,可以抛出一个异常:

from django.db.models.signals import pre_save, post_save

@receiver(pre_save)
def pre_save_handler(sender, instance, *args, **kwargs):
    # some case
    if case_error:
        raise Exception('OMG')

撰写回答