Pregunta Validación del modelo Django ManyToMany


Tengo un modelo con ManyToManyField similar a este (el modelo Word también tiene un lenguaje):

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

Al intentar agregar una nueva oración (por ejemplo, a través de django admin) recibo 'Sentence' instance needs to have a primary key value before a many-to-many relationship can be used. Esto significa que no puedo acceder a self.words antes de guardarlo, pero esto es exactamente lo que estoy tratando de hacer. ¿Hay alguna manera de evitar esto para que pueda validar este modelo sin embargo? Realmente quiero validar directamente los campos del modelo.

Encontré muchas preguntas sobre esta excepción, pero no pude encontrar ayuda para mi problema. ¡Apreciaria cualquier sugerencia!


32
2017-11-02 19:52


origen


Respuestas:


No es posible hacer esta validación en el modelo clean método, pero puede crear un modelo que pueda validar la elección de 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

A continuación, puede personalizar su Sentence modelo de clase de administrador, para usar su formulario en el administrador de Django.

class SentenceAdmin(admin.ModelAdmin):
    form = SentenceForm

admin.register(Sentence, SentenceAdmin)

45
2017-11-02 20:30



No puedes hacerlo desde el clean método en el modelo. Simplemente no es posible con la forma en que las relaciones M2M funcionan en Django. Sin embargo, puede hacer este tipo de validación en los formularios utilizados para crear un Sentence como en el administrador o un formulario en su sitio.


1
2017-11-02 20:31