2010-12-26 12 views
1

djangoのpost_save/pre_save信号を把握するのに苦労しています。Djangoのpre_save/post_saveデータを変更する

私のモデルにstatusというフィールドがあり、このモデルへのエントリが追加/保存されると、それに応じてステータスが変更される必要があります。

私のモデルは次のようになります。

class Ticket(models.Model):  
    (...) 
    status = models.CharField(max_length=1,choices=OFFERT_STATUS, default='O') 

そしてpre_save用に設定私のシグナルハンドラ、:今すぐ

def ticket_handler(sender, **kwargs): 
    ticket = kwargs['instance'] 
    (...) 
    if someOtherCondition: 
     ticket.status = 'C' 

、私はticket.save()ちょうどこの最後の行を怒鳴るif文がある置けば何が起こりますかこのアクションは信号そのものを呼び出すため、大きな反復ブラックホールです。そして、この問題はpre_savepost_saveの両方で発生します。

まあ...私はそれを保存する前(または後に)エントリを変更する能力は、djangoの世界ではかなり一般的だと思います。それで、私はここで間違っていますか?信号は間違ったアプローチですか、私はここで何か他のものを見逃していますか?

また、このpre_save/post_save関数がトリガーされると、別のモデルのインスタンスにアクセスし、その特定の行エントリを変更することは可能でしょうか?

おかげ

答えて

7

の信号は、保存する前に、同じモデル内のフィールドを更新するための適切なアプローチではありません。このケースの信号を使用する代わりに、モデルのsaveメソッドをオーバーライドします。

def save(self, force_insert=False, force_update=False): 
    status = whatever.... 
    super(Ticket, self).save(force_insert, force_update) 

他のモデルのアップデートについては、モデルを簡単にデカップリングできるため、信号が優れています。具体的には、pre_/post_save信号を追加して、保存されたモデルのコードを変更することなくアクションをトリガすることができます(サードパーティの別のアプリケーションに存在する可能性があります)。

+0

最後の段落で説明したこのケースでも、他のモデルのエントリにアクセスして変更したいですか? – Rodrogo

+0

それは信号が良いアプローチです、あなたのモデルはよりデカップリングされます –

+0

私はまた、保存後のアクションのための信号を使用します。私はモデルにすでにIDを持っている必要があります(例えば、オブジェクトIDのハッシュに基づくキーである他のフィールドを計算するためにIDを使用する場合) –

3

これは、save()に属するかもしれないCarlesに同意します。 とする必要がある場合は、信号でこれを実行してください。save()の周りに非常に緊密な状態があることを確認してください。あなたがこの方法を行って、テストで無限再帰に取得することはできません

if someOtherCondition and ticket.status != 'C': 
     ticket.status = 'C' 
     ticket.save() 

:あなたのテストは、ようrewrtittenすることができます。

+0

実際には、このsave()コールを追加しないと、ユーザーモデルが保存されていません。 frozen_setがpre_save()フックに渡されたために他のフィールドが変更できないことを意味しますか? – Davy

+0

言うことはできません。私はDjangoと 'frozenset'をすばやく検索し、2年前から[この固定チケット](https://code.djangoproject.com/ticket/24521)しか見つけられませんでした。 –

関連する問題