Django form validation

Question:

Is there an easier way to write validation for each item in a form? Maybe embed them in model declaration itself?

class InfoUpdateForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = [ 
                   'first_name',
                   'middle_name',
                   'last_name'
                 ]

    def clean(self):
        cleaned_data = super().clean()

        first_name = cleaned_data.get('first_name')
        if not str(first_name).isalnum():
            self._errors['first_name'] = self.error_class(['First name should constain only alpha numeric characters'])           
        middle_name = cleaned_data.get('middle_name')
        if not str(middle_name).isalnum():
            self._errors['middle_name'] = self.error_class(['Middle name should constain only alpha numeric characters'])           
        last_name = cleaned_data.get('last_name')
        if not str(last_name).isalnum():
            self._errors['last_name'] = self.error_class(['Last name should constain only alpha numeric characters'])  
Asked By: Jean

||

Answers:

If you want to keep the ModelForm one way is to move the validation to models.py file (as you thought) and write custom validator:

validators.py

from django.core.exceptions import ValidationError

def is_alpha_numeric(value):
    if not str(value).isalnum():
        raise ValidationError(
            ('%(value)s is not alpha-numeric'),
            params={'value': value},
        )

models.py:

from .validators import is_alpha_numeric

class Profile(models.Model):
    first_name = models.CharField(max_length=100, validators=[is_alpha_numeric])
    middle_name = models.CharField(max_length=100, validators=[is_alpha_numeric])
    last_name = models.CharField(max_length=100, validators=[is_alpha_numeric])

forms.py:

class InfoUpdateForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = [ 
                   'first_name',
                   'middle_name',
                   'last_name'
                 ]

EDIT:

To pass any kind of extra param, in your case the field name:

validators.py

class AlphaNumericValidator:
    def __init__(self, **kwargs):
        self.field_name = kwargs['name']

    def __call__(self, value):
        if not str(value).isalnum():
            raise ValidationError(
                f'{self.field_name} value "{value}" is not alpha-numeric'
            )

models.py

class Profile(models.Model):
    first_name = models.CharField(
        max_length=100, 
        validators=[AlphaNumericValidator(name='first_name')]
    )

    middle_name = models.CharField(
        max_length=100, 
        validators=[AlphaNumericValidator(name='middle_name')]
    )

    last_name = models.CharField(
        max_length=100, 
        validators=[AlphaNumericValidator(name='last_name')]
    )
Answered By: Niko
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.