Подтвердить что ты не робот

Отменить сохранение модели при использовании pre_save в django

У меня есть модель:

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

Но когда я вызываю A.save(), я хочу убедиться, что число является простым (или другими условиями), или команда сохранения должна быть отменена.

Итак, как я могу отменить инструкцию сохранения в приемнике сигнала pre_save?

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

Ответ 1

См. мой другой ответ: fooobar.com/questions/54491/...

Этот случай является нормальным, если мы просто хотим предотвратить сохранение, выведите исключение:

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')

Ответ 2

Я не уверен, что вы можете отменить сохранение только с использованием сигнала pre_save. Но вы можете легко достичь этого, переопределив метод сохранения:

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

Как уже упоминалось @Raptor, вызывающий абонент не будет знать, было ли сохранение успешным или нет. Если это необходимо для вас, посмотрите на другой ответ, который заставляет вызывающего абонента иметь дело с "несохраняющим" случаем.

Ответ 3

Если данные всегда поступают из формы, и у вас есть простой тест на наличие или отсутствие сохранения, отправьте его через validator. Обратите внимание, однако, что валидаторы не вызываются для вызовов save(), исходящих из бэкэнд. Если вы хотите, чтобы те были защищены, вы можете создать собственное поле, скажем class PrimeNumberField(models.SmallIntegerField) Если вы запустите свой тест и создаете исключение в to_python() метод этого настраиваемого поля, это предотвратит сохранение. Вы также можете подключить проверку определенного поля переопределить любой из нескольких других методов в поле, форме или Model.