[Django]-Clean() method in model and field validation

11đź‘Ť

âś…

I guess that’s the way to go:

class TrialForm(ModelForm):

    class Meta:
        model = Trial

    def clean(self):
        data = self.cleaned_data
        if not ('movement_start' in data.keys() and 'trial_start' in data.keys()  and 'trial_stop' in data.keys()):
            raise forms.ValidationError("Please fill out missing fields.")

        trial_start = data['trial_start']
        movement_start = data['movement_start']
        trial_stop = data['trial_stop']

        if not (movement_start >= trial_start):
            raise forms.ValidationError('movement start must be >= trial start')

        if not (trial_stop >= movement_start):
            raise forms.ValidationError('trial stop must be >= movement start')

        if not (trial_stop > trial_start):
            raise forms.ValidationError('trial stop must be > trial start')

        return data

EDIT the downside of this approach is, that value checking will only work if I create objects through the form. Objects that are created on the python shell won’t be checked.

👤memyself

6đź‘Ť

I know this is late, but to answer why this might be happening for people who end up here: There’s no “original clean”. The clean method is a hook for custom validation, so you are the one who provides its code. Not sure how OP was using the clean hook, but: After defining it you should be calling full_clean() over your models so that Django runs model validation in its entirety. See the details in the docs for the order in which it calls the different validation methods and such https://docs.djangoproject.com/en/1.11/ref/models/instances/#validating-objects (perhaps important to note: full_clean() isn’t automatically called by a model’s save() which is part of why when you use the shell and save straight away you’ll be skipping the validation)

(note ModelForms also have various validation steps and will call a model’s full_clean: https://docs.djangoproject.com/en/1.11/topics/forms/modelforms/#validation-on-a-modelform )

👤Lyserg Zeroz

1đź‘Ť

I’m struggling with a similar issue but with a ForeignKey. In your case, I would just check that the fields are not empty, and I would simplify your Boolean expressions:

class Trial(models.Model):

    trial_start = DurationField()
    movement_start = DurationField()
    trial_stop = DurationField()


    def clean(self):
        from django.core.exceptions import ValidationError
        if self.trial_start:
            if self.movement_start and self.movement_start < self.trial_start:
                raise ValidationError('movement start must be >= trial start')
            if self.trial_stop:
                if self.trial_stop <= self.trial_start:
                    raise ValidationError('trial stop must be > trial start')
                if self.movement_start:
                    if self.trial_stop < self.movement_start:
                        raise ValidationError('trial stop must be >= movement start')
👤Bobort

1đź‘Ť

You can add the following code in your model:

def save(self, *args, **kwargs):
    self.full_clean()
    return super().save(*args, **kwargs)

With this wherever you create your object (form, view, shell, test) the validation will be called.

Leave a comment