8

保留中、アクティブ化、拒否の3つの値を持つステータスフィールドがあります。ステータスの値を変更する場合、アクティブ化を保留に変更できないことを確認したいと思います。このためにストアドプロシージャを記述したくありません。保存する前にDjangoで以前の値を取得できますか?

新旧の価値を意味します。

4

5 に答える 5

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()に追加することもできます。Django のドキュメントを参照してください。forms.Field

于 2009-05-15T13:34:23.270 に答える
9

これは、オーバーライドされた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 プロジェクトがありますが、これは数か月間は準備ができていません。

管理者で同様のことをしたい場合、オーバーライドされたメソッドでカスタム ModelForm を定義するのが最善のclean()方法です。ただし、今回はこれがフォームであるため、再度データベースにアクセスすることなく、古い値にアクセスできます。もう 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
于 2009-05-15T06:35:08.113 に答える
1

これは Stack Overflow の他の場所で回答されていますが、正しい方法は、このようなものを使用してフィールドがダーティかどうかを追跡することです。次に、シグナルを使用して、重要な何かが変更されたことを示すことができます。(つまり、あなたの分野)

于 2011-11-10T19:28:50.377 に答える
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)
于 2012-02-20T19:35:59.207 に答える
0

save メソッドをオーバーライドする代わりに、これはシグナルを使用するのに適した場所ではないでしょうか? コミット前に保存を傍受し、データベースの現在の値を確認して、保存を転送するか拒否しますか?

シグナルが保存リクエストをブロックするのか、それとも非同期に発生するのかはわかりません。検証時に保存が発生するのを防ぐためにシグナルを使用できない場合は、この回答に反対票を投じてください。

同様に機能する別の組み込みツールがある場合、組み込みメソッドをオーバーライドすることには反対です。

于 2009-05-15T10:47:26.837 に答える