Как использовать метод чистой модели в django и перебирать поля - PullRequest
0 голосов
/ 01 октября 2019

Я задал вопрос и, поскольку я немного прочитал, теперь я могу лучше выразить то, что мне нужно: Как выполнить проверку настраиваемого поля на уровне модели в django?

У меня естьэта модель:

class StudentIelts(Model):

    SCORE_CHOICES = [(i/2, i/2) for i in range(0, 19)]

    student = OneToOneField(Student, on_delete=CASCADE)
    has_ielts = BooleanField(default=False,)
    ielts_listening = FloatField(choices=SCORE_CHOICES, null=True, blank=True, )
    ielts_reading = FloatField(choices=SCORE_CHOICES, null=True, blank=True, )
    ielts_writing = FloatField(choices=SCORE_CHOICES, null=True, blank=True, )
    ielts_speaking = FloatField(choices=SCORE_CHOICES, null=True, blank=True, )

и имеет эту модель формы:

class StudentIeltsForm(ModelForm):

    class Meta:
        model = StudentIelts
        exclude = ('student')

    def clean(self):
        cleaned_data = super().clean()
        has_ielts = cleaned_data.get("has_ielts")

        if has_ielts:
            msg = "Please enter your score."
            for field in self.fields:
                if not self.cleaned_data.get(str(field)):
                    self.add_error(str(field), msg)

        else:
            for field in self.fields:
                self.cleaned_data[str(field)] = None
                self.cleaned_data['has_ielts'] = False

        return cleaned_data

Что я здесь делаю, так это то, что при проверке, если has_ielts равно True, тогда все остальные поля должны бытьзаполнены. Если has_ielts равно True и даже одно поле не заполнено, я получаю сообщение об ошибке. Если has_ielts равно False, объект с has_ielts=False и всеми другими полями Null должны быть сохранены. Теперь я хочу сделать это на уровне модели:

class StudentIelts(Model):

    SCORE_CHOICES = [(i/2, i/2) for i in range(0, 19)]

    student = OneToOneField(Student, on_delete=CASCADE)
    has_ielts = BooleanField(default=False,)
    ielts_listening = FloatField(choices=SCORE_CHOICES, null=True, blank=True, )
    ielts_reading = FloatField(choices=SCORE_CHOICES, null=True, blank=True, )
    ielts_writing = FloatField(choices=SCORE_CHOICES, null=True, blank=True, )
    ielts_speaking = FloatField(choices=SCORE_CHOICES, null=True, blank=True, )

    def clean(self):
    # I do not know what to write in here

и иметь такую ​​модель:

class StudentIeltsForm(ModelForm):

    class Meta:
        model = StudentIelts
        exclude = ('student')

В чистом методе моей модели я хочу что-то с этой логикой (этотакое псевдо-код):

def clean(self):
    msg = "Please enter your score."

    if self.has_ielts:
        my_dic = {}
        for f in model_fields:
             if f is None:
                  my_dic.update{str(field_name): msg}
        raise ValidationError(my_dic)

Как я могу это сделать?
Как я могу получить тот же результат, что и моя модель, но на уровне модели?

1 Ответ

1 голос
/ 01 октября 2019

Вам необходимо явно объявить поля, которые должны быть непустыми, в противном случае вы циклически просматриваете поля, не связанные с вашим чистым методом, например id и student. Кто-то может захотеть добавить поле позже, которое не является обязательным, и задается вопросом, почему возникает ошибка проверки.

class StudentIelts(Model):

    # fields

    non_empty_fields = ['ielts_reading', ...]

    def clean(self):
        errors = {}
        if self.has_ielts:
            for field_name in self.non_empty_fields:
                if not getattr(self, field_name):
                    errors[field_name] = msg
        if errors:
            raise ValidationError(errors)

...