I have a model with a ManyToManyField similar to this one (the model Word has a language, too):
class Sentence(models.Model):
words = models.ManyToManyFi
According to Django docs you can listen to the m2m_changed signal, which will trigger pre_add and post_add actions.
Using add() with a many-to-many relationship, however, will not call any save() methods (the bulk argument doesn’t exist), but rather create the relationships using QuerySet.bulk_create(). If you need to execute some custom logic when a relationship is created, listen to the m2m_changed signal, which will trigger pre_add and post_add actions.
You can't do it from the clean
method on the model. It's simply not possible with the way M2M relationships work in Django. However, you can do this sort of validation on forms used to create a Sentence
such as in the admin or a form on your site.
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)