web-dev-qa-db-ja.com

django)でpre_saveを使用する場合は、モデルの保存をキャンセルしてください

私はモデルを持っています:

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?
21
Alfred Huang

私の別の答えを参照してください: 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')
20
Alfred Huang

Pre_saveシグナルのみを使用して保存をキャンセルできるかどうかはわかりません。ただし、saveメソッドをオーバーライドすることで、これを簡単に実現できます。

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

@Raptorが述べたように、呼び出し元は保存が成功したかどうかを知りません。これが要件である場合は、 その他の回答 を確認してください。これにより、呼び出し元は「保存されていない」ケースに対処する必要があります。

9

データが常にフォームからのものであり、保存を実行する必要があるかどうかを簡単にテストできる場合は、 バリデーター を介してデータを送信します。ただし、バックエンドで発生するsave()呼び出しに対してバリデーターは呼び出されないことに注意してください。それらも保護したい場合は、カスタムフィールドを作成できます。たとえば、class PrimeNumberField(models.SmallIntegerField)テストを実行して、そのカスタムの to_python()メソッド で例外を発生させた場合フィールド、それは保存を防ぎます。フィールド、フォーム、または モデル他のいくつかのメソッドのいずれかをオーバーライドする によって、特定のフィールドの検証にフックすることもできます。

4
Sarah Messer