Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Form Validation Reversed

Django Version 1.10.5

I can't find this answer in the documentation or the code source. Using the example form below I am expecting my form validation on submit to run in the order of which I have defined.

So validators.RegexValidator, validators.MinLengthValidator, etc... would run in that order. However when submitting the form it would appear that the validators are running in a reversed order.

Where validate_status, validate_employee_id, etc... would run.

Is this expected?

class FormLogin(forms.Form):
    # Employee ID
    employee_id = forms.CharField(
        label=_('employeeId'),
        required=True,
        widget=forms.TextInput(
            attrs={
                'id': 'employee_id',
                'placeholder': _('employeeId'),
                'class': 'form-control'
            }
        ),
        validators=[
            validators.RegexValidator('^[1-9][0-9]*$', _('validatorStartsWithZero'))
            validators.MinLengthValidator(1),
            validators.MaxLengthValidator(20),
            validate_employee_id,
            validate_status
        ]
    )

Currently I have 1 user with the ID of 1.

When I submit the form using 01, the validate_status validator is taking over and returning that a user doesn't even exist. I would have expected the validators.RegexValidator to be returned first because it has a 0 in front.

If I reversed the entire order of validators, then the validation appears to work in the order I wanted. But now code readability isn't clear that's what is actually happening.

Edit 1 Cleaned up example with more information

like image 663
Diemuzi Avatar asked Nov 08 '22 02:11

Diemuzi


1 Answers

I wrote this little test code to reproduce this.

from django import forms


def validate_1(value):
    print('RUNNING VALIDATOR 1')
    raise ValidationError(
        'validation error 1',
        params={'value': value},
    )

def validate_2(value):
    print('RUNNING VALIDATOR 2')
    raise ValidationError(
        'validation error 2',
        params={'value': value},
    )


class FormLogin(forms.Form):
    # Employee ID
    employee_id = forms.CharField(validators=[
        validate_1,
        validate_2
    ])

Running it:

>>> f = FormLogin({'employee_id': '01'})
>>> f.is_valid()
RUNNING VALIDATOR 1
RUNNING VALIDATOR 2
False
>>> f.errors
{'employee_id': ['validation error 1', 'validation error 2']}
>>> 

As you can see, the validators where executed in descending order.

I assume that one of your self written validators does not properly throw a ValidationError so that the list of errors get's messed up or that you do not properly render the errors in your template.

Normally all validators will run and every validation error will be appended to the list of errors. But they run in descending order.

like image 76
trixn Avatar answered Nov 15 '22 06:11

trixn