2011-11-02 12 views
30

私は(あまりにも、Wordの言語を持っているモデル)この1に類似のManyToManyFieldでモデルを持っている:Djangoの多対多モデル検証

class Sentence(models.Model): 
    words = models.ManyToManyField(Word) 
    language = models.ForeignKey(Language) 
    def clean(self): 
     for word in self.words.all(): 
      if word.language_id != self.language_id: 
       raise ValidationError('One of the words has a false language') 

新しい文を追加しようとしている(例えばDjangoの管理者を介して)I 'Sentence' instance needs to have a primary key value before a many-to-many relationship can be usedを入手してください。つまり、保存する前にself.wordsにアクセスすることはできませんが、これはまさに私がやろうとしていることです。それにもかかわらず、あなたはこのモデルを検証することができます回避するための方法はありますか?モデルのフィールドを直接検証したいと思っています。

この例外に関する多くの質問がありましたが、私の問題のヘルプが見つかりませんでした。私はどんな提案もありがとう!

+0

Wordを作成する場合は、それがSentenceに関連付けられていることをどのように検証しますか?モデル定義に「文章」フィールドはありません。 – johnklawlor

+0

誰もがフォームを使用しているわけではありません。私はこれをDjangoの大きな欠陥と考えています。誰かがより良い答えを持っていますか? –

答えて

44

モデルのcleanメソッドでこの検証を行うことはできませんが、wordsの選択を検証できるモデルフォームを作成できます。

from django import forms 

class SentenceForm(forms.ModelForm): 
    class Meta: 
     model = Sentence 

    def clean(self): 
     """ 
     Checks that all the words belong to the sentence's language. 
     """ 
     words = self.cleaned_data.get('words') 
     language = self.cleaned_data.get('language') 
     if language and words: 
      # only check the words if the language is valid 
      for word in words: 
       if words.language != language: 
        raise ValidationError("The word %s has a different language" % word) 
     return self.cleaned_data 

その後、Djangoのadminにあなたのフォームを使用して、あなたのSentenceモデルの管理クラスをカスタマイズすることができます。

class SentenceAdmin(admin.ModelAdmin): 
    form = SentenceForm 

admin.register(Sentence, SentenceAdmin) 
+6

モデルで直接検証することはできません。しかし、これまでのカスタムModelFormで十分です。あなたの答えをありがとう! – purefanatic

+0

また、Sentenceフォームを別のモデル(たとえば段落)のインラインとして見ることもできる場合は、 'form = SentenceForm'という行もSentenceInlineクラスに追加することをお勧めします。 –

+0

@purefanatic 'Model.save()'は 'ValidationErrors'を呼び出す予定はないので、直接バリデーションを行う方法はありません。 – jnns

1

モデルのcleanメソッドからは実行できません。 DjangoでM2M関係が動作する方法は、単に不可能です。ただし、管理者やサイトのフォームなどでSentenceを作成するために使用するフォームで、この種の検証を行うことができます。

関連する問題