Проверка модели Django ManyToMany - PullRequest
35 голосов
/ 02 ноября 2011

У меня есть модель с ManyToManyField, похожая на эту (модель Word также имеет язык):

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) я получаю 'Sentence' instance needs to have a primary key value before a many-to-many relationship can be used. Это означает, что я не могу получить доступ к self.words перед сохранением, но это именно то, что я пытаюсь сделать. Есть ли способ обойти это, чтобы вы все же могли проверить эту модель? Я действительно хочу напрямую проверить поля модели.

Я нашел много вопросов, касающихся этого исключения, но не смог найти помощь по моей проблеме. Буду признателен за любые предложения!

Ответы [ 3 ]

49 голосов
/ 03 ноября 2011

Невозможно выполнить эту проверку в методе 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

Затем можно настроитьSentence класс администратора, чтобы использовать вашу форму в админке Django.

class SentenceAdmin(admin.ModelAdmin):
    form = SentenceForm

admin.register(Sentence, SentenceAdmin)
1 голос
/ 03 ноября 2011

Вы не можете сделать это с помощью метода clean на модели.Это просто невозможно с тем, как M2M-отношения работают в Django.Тем не менее, вы можете выполнять такую ​​проверку в формах, используемых для создания Sentence, таких как администратор или форма на вашем сайте.

0 голосов
/ 30 мая 2019

Согласно Django docs вы можете прослушивать сигнал m2m_changed , который вызовет действия pre_add и post_add .

Использование add () с отношением «многие ко многим», однако, не вызовет никаких методов save () (массовый аргумент не существует), но создаст отношения с помощью QuerySet.bulk_create (),Если вам нужно выполнить некоторую пользовательскую логику при создании отношения, прослушайте сигнал m2m_changed, который вызовет действия pre_add и post_add.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...