2012-01-07 19 views
38

モデルのsaveメソッドで検証エラーを適切に発生させ、クリアメッセージをユーザーに返す方法がわかりません。Djangoでモデルのsaveメソッドで検証エラーを発生する

基本的に私は、私はエラー を調達したいもの、それは実際にセーブ1を終了しなければならない「場合」の方法を各部分を知りたい:

def save(self, *args, **kwargs): 
    if not good_enough_to_be_saved: 
     raise ValidationError 
    else: 
     super(Model, self).save(*args, **kwargs) 

その後、私は知りたいですたとえば、値が一意でない場合、Djangoが自動的に返すものと同じように、何が間違っているのかを正確にユーザーに知らせる検証エラーを送信するにはどうすればよいですか。 私は(ModelForm)を使用しており、モデルのすべてを調整しています。

答えて

32

ほとんどのDjangoビューDjango管理者はsaveメソッドで検証エラーを処理できないため、ユーザーには500のエラーが発生します。

モデルフォームまたはモデルで検証を行い、ValidationErrorを呼び出す必要があります。その後、モデルフォームデータが「保存するのに十分である」場合にのみ、save()を呼び出します。

django 1.2 it is able to write validation code on modelので:

+0

あなたは右の私はに私の検証を移動しますねフォーム、それは簡単です。私はちょうどモデルのすべてを持っているという考えが好きだった。 – Bastian

+8

@bastian、私はモデルのすべてを持っていることも好きだった。新しいフォームを書くときビジネスルールを忘れるのは簡単ですが、ビジネスルールがモデルにある場合はそうではありません。この理由から私は自分の投稿で説明するように、フォームからモデルに検証を移しました。私はそれが存在する場合、よりエレガントな方法でこれを行う新しい方法について学ぶために開いています。いずれにしても、フォームに検証コードを書くことは避けてください。 – danihp

+6

バリデータを使用するか、 'clean()'メソッドを書くことでモデルにバリデーションを入れることは良いことです。私が言っていたのは、 'save()'メソッドは正しい場所ではないということです。 [validating objects](https://docs.djangoproject.com/en/dev/ref/models/instances/#validating-objects)のドキュメントをご覧ください。 – Alasdair

22

バスティアンは、私は私のコードのテンプレートあなたに説明し、私はあなたに役立ちます願っています。 modelformsを使用する場合、フォーム検証時にinstance.full_clean()が呼び出されます。各モデルで

私は(のModelFormの検証に、このメソッドが自動的に(full_cleanから呼び出される))カスタム関数でclean()メソッドを上書き:

from django.db import models 

class Issue(models.Model): 
    .... 
    def clean(self): 
     rules.Issue_clean(self) #<-- custom function invocation 

from issues import rules 
rules.connect() 

はその後rules.pyファイルに私は商務ルールを記述します。また、私は間違った状態でモデルを救う防ぐために、私のカスタム関数にpre_save()を接続します

issues.models輸入問題

def connect():  
    from django.db.models.signals import post_save, pre_save, pre_delete 
    #issues 
    pre_save.connect(Issue_pre_save, sender = Incidencia) 
    post_save.connect(Issue_post_save, sender = Incidencia) 
    pre_delete.connect(Issue_pre_delete, sender= Incidencia) 

def Incidencia_clean(instance): #<-- custom function 
    import datetime as dt  
    errors = {} 

    #dia i hora sempre informats  
    if not instance.dia_incidencia: #<-- business rules 
     errors.setdefault('dia_incidencia',[]).append(u'Data missing: ...') 

    #dia i hora sempre informats  
    if not instance.franja_incidencia: 
     errors.setdefault('franja_incidencia',[]).append(u'Falten Dades: ...') 

    #Només es poden posar incidències més ennlà de 7 dies 
    if instance.dia_incidencia < (dt.date.today() + dt.timedelta(days = -7)): 
     errors.setdefault('dia_incidencia 1',[]).append(u'''blah blah error desc)''') 

    #No incidències al futur. 
    if instance.getDate() > datetime.now(): 
     errors.setdefault('dia_incidencia 2',[]).append(u'''Encara no pots ....''') 
    ... 

    if len(errors) > 0: 
     raise ValidationError(errors) #<-- raising errors 

def Issue_pre_save(sender, instance, **kwargs): 
    instance.clean()  #<-- custom function invocation 

からその後、のModelFormがモデルのクリーンな方法と右の状態のための私のcuston機能チェックを呼び出しますモデル・フォームで処理されるエラーを発生させることがあります。

フォーム上のエラーを表示するには、フォームテンプレートでこれを含める必要があります。

{% if form.non_field_errors %} 
     {% for error in form.non_field_errors %} 
     {{error}} 
     {% endfor %} 
{% endif %} 

理由は、モデル検証errosのアラがnon_field_errorsエラー辞書のエントリにバインドさという点です。

あなたはエラーが発生することができることを覚えておいてくださいフォームのうち、モデルを保存または削除:

try: 
    issue.delete() 
except ValidationError, e: 
    import itertools 
    errors = list(itertools.chain(*e.message_dict.values())) 

また、あなたがいないmodelforms上のフォーム辞書にエラーを追加することができます。

try: 
     #provoco els errors per mostrar-los igualment al formulari. 
     issue.clean() 
    except ValidationError, e: 
     form._errors = {} 
     for _, v in e.message_dict.items(): 
      form._errors.setdefault(NON_FIELD_ERRORS, []).extend( v ) 

このコードはsave()メソッドでは実行されないことに注意してください。モデルのsave()メソッドを呼び出すとき、またはModelForm検証の結果としてfull_clean()が自動的に呼び出されることはありません。その後、あなたはなしmodelforms上のフォーム辞書にエラーを追加することができますだけでなくValidationErrorををインポートするようにしてください

try: 
     #provoco els errors per mostrar-los igualment al formulari. 
     issue.clean() 
    except ValidationError, e: 
     form._errors = {} 
     for _, v in e.message_dict.items(): 
      form._errors.setdefault(NON_FIELD_ERRORS, []).extend( v ) 
+1

あなたの長らくの説明のためのモルトのgràcies。私は何か自動、Djangoishを探していました。あなたの例は他の状況に興味があるかもしれませんが、私が今書いているのはただ1行のバリデーションだけなので、ここではすべてを実装しません。 – Bastian

+3

あなたは大歓迎です。私はバルセロナを訪問することを忘れないでください:) – danihp

+7

私はバルセロナに住んでいます:) – Bastian

1

from django.core.exceptions import ValidationError 
-1
def clean(self): 
    raise ValidationError("Validation Error") 

def save(self, *args, **kwargs): 
    if some condition: 
     #do something here 
    else: 
     self.full_clean() 
    super(ClassName, self).save(*args, **kwargs) 
+1

投稿コードは不十分です。 – Ivan

+0

保存関数でfull_clean()メソッドを呼び出すことはできますが、これはDjango == 1.11で問題なく動作しますが、古いバージョンについてはわかりません。 –

+0

この情報を改善のために回答に追加してください。 – Ivan

関連する問題