2009-05-15 9 views
8

ステータスフィールドには、保留中の という3つの値があり、拒否されました。ステータスの値を変更している場合は、 にチェックを入れて、有効化を保留に変更することはできません。 I これのためにstored-procsを書きたくありません。保存する前にDjangoに の前の値を設定できますか?Django(django-admin)の値の推移を確認する方法は?

新しい値と古い値を意味します。

+0

1 - 私は同じことを思ってきました。私の場合は、モデルのフィールドの特定のサブセットのフィールドが変更されている場合にのみ必要なセーブメソッドで行われる重大な作業があります。これがそうであるかどうかを確認する方法を探しています。ありがとう! –

答えて

10
def clean_status(self): 
    status = self.cleaned_data.get('status') 
    if status == 'pending': 
     if self.instance and self.instance.status == 'activated': 
      raise forms.ValidationError('You cannot change activated to pending') 

    return status 

このメソッドは、Formサブクラスに追加されます。その名前はclean_FIELD_NAMEです。

cleaned_dataは、以前の値が含まれています。新しい値はself.instanceに格納されます。

あるいは、validate()方法はforms.Fieldサブクラスに添加することができます。 See Django documentation.

+0

ちょっとドミニクロガーは、 'インライン - django'で助けることができます。私の質問django – ha22109

8

あなたは上書きsave方法でこれを行うことができます。覚えておくべきことは、Djangoのモデルインスタンスは実際のデータベースオブジェクトではなく、ロード時にそこから値を取得するということです。既存の値を取得するために、現在のオブジェクトを保存する前に簡単にデータベースに戻ることができます。

def save(self, *args, **kwargs): 
    if self.status == 'pending': 
     old_instance = MyClass.objects.get(pk=self.pk) 
     if old_instance.status == 'activated': 
       raise SomeError 
    super(MyModel, self).save(*args, **kwargs) 

現在、例外を発生する以外にエラーメッセージをユーザーに返す良い方法はありません。 「モデル検証」を有効にするGoogle Summer of Codeプロジェクトが現在進行中ですが、これは数か月は準備ができません。

adminで同様のことを行う場合は、オーバーライドされたclean()メソッドを使用してカスタムModelFormを定義することをお勧めします。しかし、今回はこれがフォームなので、すでにDBにアクセスすることなく古い値にアクセスすることができます。もう1つの利点は、ユーザーにフォーム検証エラーを返すことができることです。

class MyModelForm(forms.ModelForm): 

    class Meta: 
      model = MyModel 

    def clean_status(self): 
     status = self.cleaned_data.get('status', '') 
     if status == 'pending': 
      if self.instance and self.instance.status == 'activated': 
        raise forms.ValidationError(
         'You cannot change activated to pending' 
       ) 
     return status 

class MyModelAdmin(forms.ModelAdmin): 
    form = MyModelForm 
    model = MyModel 
+0

これはおそらくModelAdmin.save_modelメソッドをオーバーライドする必要があるからです:http://docs.djangoproject.com/en/dev/ref/contrib/admin/#modeladmin-methods – ohnoes

+0

上記の管理者を使って代替案を追加しました。 –

+0

if条件は である必要があります。self.instanceとself.instance.status == 'activated': raise forms.ValidiationError – ha22109

0

saveメソッドをオーバーライドする代わりに、これはシグナルを使用するのに適していませんか?コミットする前にセーブを傍受し、データベースの現在の値をチェックし、セーブをオンにするか、拒否しますか?

は今、私は信号ブロックが要求を保存したり、それが非同期に発生した場合、その信号は、検証時に起こって保存しないようにするために使用することができない場合は、この答えをdownvoteして自由に感じるかはわかりません。

同じようにうまく動作し、他の作り付けのツールがあれば、私はオーバーライド作り付けの方法に反対です。

+1

save()とdelete()を上書きするのは良い方法です。 私は写真とサムネイルのクラスを持っています。 Thumbにはアイテム= models.ForeignKey(写真)があります。 super(Photo、self).delete()を実行する前にphoto.delete()を上書きし、すべてのサムを削除します(self.thumbnail_set.all()内のt:t.delete())。 親指の除去が信号で行われる場合、コードの維持はより困難になります。 – vikingosegundo

+0

しかし__init__私は決して過負荷になりません。私は代わりに信号を使用します。 – vikingosegundo

1

これはスタックオーバーフローの別の場所で回答されていますが、正しい方法はthisのようなフィールドを使用してフィールドが汚れているかどうかを調べることです。それから、重要なことが何か変わったことを示すために信号を使うことができます。 (あなたのフィールド)

0

同じ質問に対する回答を探している間にこのスレッドが見つかりました。なぜこのようなことをしないのですか?これにより、データベースに触れることを避けることができます。そして、組み込みの__init__ちょっと拡張しました。信号を使うよりもずっと簡単だと思います。

class MyModel(models.Model): 
    my_fair_field = .... 

    def __init__(self, *args, **kwargs): 
     super(MyModel, self).__init__(*args, **kwargs) 
     self.__clean_fair_field = self.my_fair_field 

    def save(self, *args, **kwargs): 
     # check if field value changed 
     if self.__clean_fair_field != self.my_fair_field 
       # ...do some work... 

     super(MyModel, self).save(*args, **kwargs) 
関連する問題