How to handle the validation of the model form when the model has a clean method if the model form excluded some fields?

橙三吉。 提交于 2019-12-02 05:47:13

After the ModelForm is initialised, it has an instance attribute which is the model instance on which clean() will be called. So if you remove exam_date from the instance's non_empty_fields dictionary, it won't use it in clean:

class IeltsExamForm(ModelForm): 
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.instance.non_empty_fields.pop('exam_date')

And you could do that for each field in self._meta.exclude.

However, when doing that, the attribute non_empty_fields should not be a class attribute but an instance property. Modifying the instance's non_empty_fields actually modifies the class attribute (it's a dictionary so it's mutable), which will have unintended side-effects (once removed, it's removed for any subsequent instance you create). Change your model to set the attribute in the init method:

class IeltsExam(Model):
    # ...
    # remove the class attribute non_empty_fields

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.non_empty_fields = { ... }

In general, I would advise you to only use a ModelForm if you're actually going to save the model, in which case a class attribute is the cleaner approach. Instead of doing all this, if your form isn't going to save the actual model, you should not use a ModelForm but a Form and define all fields and cleaning in the form itself.

Perform the validation on model's save()

Consider the following model:

class Exam(Model):

    student = OneToOneField(Student, on_delete=CASCADE)
    has_taken_exam = BooleanField(default=False)
    score = FloatField(choices=SCORE_CHOICES, null=True, blank=True)
    exam_date = DateField(null=True, blank=True)

    def save(self, *a, **kw):
        if self.has_taken_exam and not self.exam_date:
            raise ValidationError("Exam date must be set when has_taken_exam is True")
        return super().save()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!