2013-07-15 11 views

答えて

20

私は一例でそれを説明するためにベストを尽くすものとします

pre_savepost_saveは、モデルによって送信されsignalsです。簡単な言葉では、モデルのsaveの前後に実行されるアクションが呼び出されます。

savetriggers the following steps

  • プリセーブ信号を発します。
  • データを前処理します。
  • ほとんどのフィールドには前処理は行われません。フィールドデータはそのまま維持されます。
  • データベースのデータを準備します。
  • データをデータベースに挿入します。
  • ポストセーブ信号を出力します。

Djangoはこれらの信号を無効にする方法を提供しています。実際には、データベースに保存する前に、今、

pre_save信号は、いくつかの処理のために無効にすることができ

が起こる - 例:(私はpre_saveが私の頭の上で理想的であるところの良い例を知らない)

,まだ編集されていないModelBのすべてのオブジェクトへの参照を格納しているModelAがあるとします。このため、pre_save信号を登録して、ModelBsaveメソッドが呼び出される直前にを通知することができます(ここでも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通知)私はより良いこの質問に答えるために、より具体的な現実世界の例を考えるものとします。一方で、これがあなたに役立つことを願っています。

+0

詳細な回答ありがとうございます。 'Post_save'が' UserProfile'の作成に使われたのは、post_saveでインスタンスが 'created'であるかどうかをチェックできるからです(ただし、pre_saveには保存されません)。 – eugene

+0

pre_saveまたはpost_saveは、トランザクションとはまったく関係ありません。 get_or_createを使用するか、レベルトランザクションを要求すると、post_saveはトランザクションの内側で*起こります。データベースによっては、そこにいくつかのpost_commitシグナル実装を使用することができます。 – ashwoods

3
pre_save 

トランザクションが保存される前に使用されます。

post_save 

トランザクション保存後に使用されます。

あなたはFileFieldImageFieldを持っている場合、例えばpre_saveを使用してfileまたはimageが本当に存在するかどうかを確認することができます。

post_saveは、があり、新しいUserが作成された瞬間に新しいものを作成したい場合に使用できます。

+0

ファイルが存在するかどうかを確認するための例を与えた 'pre_save'の例では、どちらの方がsignalを使うか、saveメソッドをオーバーライドする方が良いですか?なぜなら私の 'pre_save'シグナルにバリデーションを追加すると私のフォームにエラーが発生するという問題があったからです。 –

+0

@ Keda87フォームを使用している場合は、フォームの検証機能を無効にするために使用します。 –

+0

post_saveは、通常、アトムブロックで呼び出されます。つまり、post_saveは*トランザクション内で*発生します。 – ashwoods

1

再帰リスクについて忘れないでください。 あなたの代わりに.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_信号を送信しないでください。注意してください。

関連する問題