pre_save, save, post_save
をオーバーライドまたは定義して、モデルインスタンスが保存されたときに必要な作業を行うことができます。いつpre_save、save、post_saveをdjangoで使うのですか?
いずれの状況でどちらが優先され、その理由はどちらですか?
pre_save, save, post_save
をオーバーライドまたは定義して、モデルインスタンスが保存されたときに必要な作業を行うことができます。いつpre_save、save、post_saveをdjangoで使うのですか?
いずれの状況でどちらが優先され、その理由はどちらですか?
私は一例でそれを説明するためにベストを尽くすものとします
pre_save
とpost_save
は、モデルによって送信されsignalsです。簡単な言葉では、モデルのsave
の前後に実行されるアクションが呼び出されます。
save
triggers the following steps
Djangoはこれらの信号を無効にする方法を提供しています。実際には、データベースに保存する前に、今、
pre_save
信号は、いくつかの処理のために無効にすることができ
が起こる - 例:(私はpre_save
が私の頭の上で理想的であるところの良い例を知らない)
,まだ編集されていないModelB
のすべてのオブジェクトへの参照を格納しているModelA
があるとします。このため、pre_save
信号を登録して、ModelB
のsave
メソッドが呼び出される直前にを通知することができます(ここでもpost_save
シグナルの登録を停止することはできません)。
さて、モデルのsave
方法は(それが信号ではない)と呼ばれている - デフォルトでは、すべてのモデルはsave
方法がありますが、あなたはそれを上書きすることができます。
class ModelB(models.Model):
def save(self):
#do some custom processing here: Example: convert Image resolution to a normalized value
super(ModelB, self).save()
次に、あなたが登録できますpost_save
信号User
オブジェクトがシステムに登録されたとき
共通のユースケースUserProfile
オブジェクトの作成である(これはpre_save
そのより使用されています)。
User
に対応するUserProfile
オブジェクトを作成する信号post_save
を登録できます。
信号は、物事をモジュール化して明示的に保つ方法です。
を(I save
またはModelB
で何かを変更した場合、明示的にModelA
通知)私はより良いこの質問に答えるために、より具体的な現実世界の例を考えるものとします。一方で、これがあなたに役立つことを願っています。
pre_save
トランザクションが保存される前に使用されます。
post_save
トランザクション保存後に使用されます。
あなたはFileField
やImageField
を持っている場合、例えばpre_save
を使用してfile
またはimage
が本当に存在するかどうかを確認することができます。
post_save
は、があり、新しいUser
が作成された瞬間に新しいものを作成したい場合に使用できます。
ファイルが存在するかどうかを確認するための例を与えた 'pre_save'の例では、どちらの方がsignalを使うか、saveメソッドをオーバーライドする方が良いですか?なぜなら私の 'pre_save'シグナルにバリデーションを追加すると私のフォームにエラーが発生するという問題があったからです。 –
@ Keda87フォームを使用している場合は、フォームの検証機能を無効にするために使用します。 –
post_saveは、通常、アトムブロックで呼び出されます。つまり、post_saveは*トランザクション内で*発生します。 – ashwoods
再帰リスクについて忘れないでください。 あなたの代わりに.update方法を、あなたはpost_save信号を切断する必要があり、instance.save()呼び出しでpost_save方法を使用する場合:
Signal.disconnect(レシーバ=なし、送信者=なし、 dispatch_uid = None)[source]信号から受信機を切断するには、 はSignal.disconnect()を呼び出します。引数は、 Signal.connect()で説明されているとおりです。受信者が の場合はTrueを返し、そうでない場合はFalseを返します。
receiver引数は、切断する登録済みの受信者を示します。 受信者を識別するためにdispatch_uidが使用されている場合は、Noneになることがあります。
...後にもう一度接続してください。
update()メソッドはpre_信号とpost_信号を送信しないでください。注意してください。
詳細な回答ありがとうございます。 'Post_save'が' UserProfile'の作成に使われたのは、post_saveでインスタンスが 'created'であるかどうかをチェックできるからです(ただし、pre_saveには保存されません)。 – eugene
pre_saveまたはpost_saveは、トランザクションとはまったく関係ありません。 get_or_createを使用するか、レベルトランザクションを要求すると、post_saveはトランザクションの内側で*起こります。データベースによっては、そこにいくつかのpost_commitシグナル実装を使用することができます。 – ashwoods