2016-04-19 13 views
19

モデル保存後にいくつかのステートメントを実行するためにdjangoのpost_saveシグナルを使用しています。djangoの変更されたフィールドを特定するpost_saveシグナル

class Mode(models.Model): 
    name = models.CharField(max_length=5) 
    mode = models.BooleanField() 


from django.db.models.signals import post_save 
from django.dispatch import receiver 

@receiver(post_save, sender=Mode) 
def post_save(sender, instance, created, **kwargs): 
     # do some stuff 
     pass 

は、今私はmodeフィールドの値が変更されたかどうかに基づいて文を実行します。

@receiver(post_save, sender=Mode) 
def post_save(sender, instance, created, **kwargs): 
     # if value of `mode` has changed: 
     # then do this 
     # else: 
     # do that 
     pass 

私はいくつかのSOFスレッドとブログを見ましたが、これに対する解決策は見つかりませんでした。それらのすべては、私のユースケースではないpre_saveメソッドまたはフォームを使用しようとしていました。 djangoドキュメントのhttps://docs.djangoproject.com/es/1.9/ref/signals/#post-saveにはこれを直接行う方法は記載されていません。

以下のリンクの回答は有望ですが、私はそれをどのように使用するのか分かりません。私はこれをデバッグするためにipdbを使用したため、instanceに変数has_changedがあることがわかりましたので、最新のdjangoバージョンがサポートしているかどうかはわかりません。

Django: When saving, how can you check if a field has changed?

答えて

13

あなたがそれにアクセスすることができますので、お使いのモデルの__init__上でそれを設定します。 々ussuallyそれが信号を使用するよりも、保存メソッドをオーバーライドする方が良いでしょう

if instance.mode != instance.__original_mode: 
    # do something useful 
+4

注意してください。このアプローチには長所[here](http://stackoverflow.com/questions/1355150)で論じられているように、欠点があります。一言で言えば、それは競争が激しいわけではなく、2つのpythonインスタンスが同じdb行を指していると間違っている可能性もあります。 –

18

def __init__(self, *args, **kwargs): 
    super(YourModel, self).__init__(*args, **kwargs) 
    self.__original_mode = self.mode 

今、あなたは次のような何かを行うことができます。

Two scoops of django: 「信号を最後の手段として使用する」

@scoopsevenはinitの元の値をキャッシュすることについて同意しますが、可能であればsaveメソッドをオーバーライドします。

class Mode(models.Model): 
    name = models.CharField(max_length=5) 
    mode = models.BooleanField() 
    __original_mode = None 

    def __init__(self, *args, **kwargs): 
     super(Mode, self).__init__(*args, **kwargs) 
     self.__original_mode = self.mode 

    def save(self, force_insert=False, force_update=False, *args, **kwargs): 
     if self.mode != self.__original_mode: 
      # then do this 
     else: 
      # do that 

     super(Mode, self).save(force_insert, force_update, *args, **kwargs) 
     self.__original_mode = self.mode 
+1

Djangoでシグナルを使用すると何が問題になりますか?ワークフローをうまく作成するのに役立ちます。 – Hussain

+3

@Hussainメソッドはモデルに直接添付され、その動作を1か所で見ることができますが、信号を複数の異なるアプリケーションに配置し、デバッグを悪夢とコードの読みやすさを向上させることができます。だから信号が悪いのではないが、方法はより明白であり、できればそれに固執する方がよい。 –

+0

__original_modeはスレッドセーフではありません...... –

関連する問題