Custom form field validation with Django

In this post, I want to look at how Django Forms can be used to validate incoming HTTP request containing POST method.

Django comes with some useful built-in data validation methods. You can rely on these methods but there are occasions when you might have to create a custom validator to ensure the integrity of certain fields in your form.

In the first example, I want to ensure the Name field only accepts capitalised words. I should get an error message if the name doesn't start with a capital letter.

I'm going to start by creating a validators.py file.

from django.core.exceptions import ValidationError

def validate_name(value):
     """
     Raise validation error if the value
     doesn't start with a capital letter
     """
     if value != value.capitalize():
         raise ValidationError('Please capitalise the first letter: %(value)s',
                               code='invalid',
                               params={'value': value})

The code above is a function that performs a string check and raises an error if the submitted argument doesn't pass the test.

The next step is to add the custom form to the views.

class RestaurantCreate(ObjectCreateMixin, View):
     form_class = RestaurantForm
     template_name = 'restaurant/restaurant_form.html'

With the form completed, I'm going to add a new restaurant to the database.

When the first character is not capitalised in the Name field, the form returns an error.

Let's modify the validation function to ensure my new form only accepts Californian zip codes that begin with 900.

def validate_zip_code(value):
     """
     Raise a ValidationError if the value doesn't start with '900'.
     """
     if not value.startswith(u"900"):
         msg = u"Your zip code must start with 900"
         raise ValidationError(msg)

Result:

Same as above, the form returns an error if the zip code doesn't start with 900.

When writing these custom validators, if you declare them in the core app, you will comply with the DRY (Don't Repeat Yourself) principle and will be able to call them across the entire project.