Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
400 views
in Technique[技术] by (71.8m points)

Django ManyToMany model validation

I have a model with a ManyToManyField similar to this one (the model Word has a language, too):

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')

When trying to add a new sentence (e.g. through django admin) I get 'Sentence' instance needs to have a primary key value before a many-to-many relationship can be used. This means I can't access self.words before saving it, but this is exactly what I'm trying to do. Is there any way to work around this so you can validate this model nevertheless? I really want to directly validate the model's fields.

I found many questions concerning this exception, but I couldn't find help for my problem. I would appreciate any suggestions!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It is not possible to do this validation in the model's clean method, but you can create a model form which can validate the choice of words.

from django import forms

class SentenceForm(forms.ModelForm):
    class Meta:
        model = Sentence
        fields = ['words', 'language']

    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

You can then customise your Sentence model admin class, to use your form in the Django admin.

class SentenceAdmin(admin.ModelAdmin):
    form = SentenceForm

admin.register(Sentence, SentenceAdmin)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...