2012-10-18 3 views
12

あなたの時間に感謝します。Django - 保存メソッドをオーバーライドするときに古い値と新しい値との差異を確認してください

私はDjango 1.4を使用しています。次のコードがあります。Questモデルのオーバーライドされた保存メソッドです。

@commit_on_success 
def save(self, *args, **kwargs): 
    from ib.quest.models.quest_status_update import QuestStatusUpdate 
    created = not self.pk 

    if not created: 
     quest = Quest.objects.get(pk=self) 
     # CHECK FOR SOME OLD VALUE 
    super(Quest, self).save(*args, **kwargs) 

これを行うスマートな方法を見つけることができませんでした。古いインスタンス値を見つけるために私が現在更新しているオブジェクトに対して新しいクエリを作成しなければならないことは、私にとって非常に馬鹿げているようです。

これを行うより良い方法はありますか?

ありがとうございます。あなたが自分で行うか、別のクエリは前に保存を実行する必要がありますので、

サンフランシスコ

+0

更新のコンテキストとは何ですか?すなわち、モデルやModelFormなどを介して直接ビューに表示されますか? – jondykeman

+0

これは本当に関係がありますか?私はメソッドを保存してインスタンスを更新しています。しかし、とにかく、この呼び出しはビューから行われ、そこに 'quest.save()'が呼び出されました – Francisco

+0

これを行うにはクリーンな方法があるとは思えません。古いオブジェクトを 'save()'メソッドに渡したり、それを実行しているときに 'save()'でそれを照会することができます。 – Rohan

答えて

9

Djangoは、モデルインスタンスの古い値をキャッシュしません。

一つの一般的なパターンは(あなたがやったように、またはあなたのsave()メソッドで直接このコードを入れて)前セーブ信号を使用することです:

old_instance = MyModel.objects.get(pk=instance.pk) 
# compare instance with old_instance, and maybe decide whether to continue 

あなたがのキャッシュを保持したい場合

from copy import deepcopy 
object = MyModel.objects.get(pk=some_value) 
cache = deepcopy(object) 

# Do something with object, and then compare with cache before saving 

a recent discussionが他のいくつかの可能な解決策で、同様にこの程度ジャンゴ - 開発者にありました:古い値は、あなたはおそらくあなたのビューのコードであることだろう。

+0

この度はありがとうございます。これは動作しますが、 'save_as'を使う場合には、pkは' None'に設定されます。これを回避するには? –

1

私はdjango-reversion信号を使って古い値との違いをチェックしていますが、同じロジックが保存信号に当てはまります。私の違いは、フィールドが保存されたかどうかを保存したいということです。

@receiver(reversion.pre_revision_commit) 
def it_worked(sender, **kwargs): 
    currentVersion = kwargs.pop('versions')[0].field_dict 
    fieldList = currentVersion.keys() 
    fieldList.remove('id') 
    commentDict = {} 
    print fieldList 
    try: 
     pastVersion = reversion.get_for_object(kwargs.pop('instances')[0])[0].field_dict 
    except IndexError: 
     for field in fieldList: 
      commentDict[field] = "Created" 
     comment = commentDict 
    except TypeError: 
     for field in fieldList: 
      commentDict[field] = "Deleted" 
     comment = commentDict 
    else: 
     for field in fieldList: 
      try: 
       pastTest = pastVersion[field] 
      except KeyError: 
       commentDict[field] = "Created" 
      else:  
       if currentVersion[field] != pastTest: 
        commentDict[field] = "Changed" 
       else: 
        commentDict[field] = "Unchanged" 
     comment = commentDict 
    revision = kwargs.pop('revision') 
    revision.comment = comment 
    revision.save() 
    kwargs['revision'] = revision 
    sender.save_revision 
12

あなたは、initメソッド内の古い値を保存することができます

def __init__(self, *args, **kwargs): 
    super(MyModel, self).__init__(*args, **kwargs) 
    self.old_my_field = self.my_field 

def save(self, *args, **kwargs): 
    print self.old_my_field 
    print self.my_field 

あなたはおそらく、保存して削除する方法で後で使用するためにオブジェクト全体をコピーするにはdeepcopyまたは同様のものを使用することができます。

+0

スーパーシンプルで読みやすい。プラスそれは完全に動作します。優れたソリューション。 –

関連する問題