Django is an open source Python based web framework based on Model-View-Template architecture. It has a lot of modules inside it and sometimes it gets confusing for a newbie to understand why or why not some particular behaviour is happening in Django.

This small article demystifies one such topic of Form and field validation in Django. In general, the Django Form’s is_valid() method runs all the internal and custom validations. If at any stage, the value does not satisfy any of the validation then immediately a Validation Error is raised and execution of further validations stops.

Here, we will try to see that what is actually happening when we hit is_valid() method.

Internally, it calls many other methods but the validators do the actual validations. Validators are simple functions or executables which takes a single argument and raise Validation Error.

Django Form processing executes 3 types of cleaning methods mentioned below in their respective order:

  1. Field.clean() method
  2. clean_<fieldname>() method
  3. Form.clean() method

A. Field.clean() method:

The Field.clean() contains further 3 methods:

  1. to_python()
  2. validate()
  3. run_validators()

It is a Field subclass method and is responsible for running the to_python(), validate() and run_validators() in the above mentioned correct order. If at any stage, Validation Error occurs during execution of these methods. It ensures to stop validation and propagate their errors.

It returns cleaned data in a Python Dictionary named cleaned_data.

B. clean_<fieldname>():

Next comes clean_<fieldname>() method. It is a Form subclass method, where <fieldname> replaces the name of the form field attribute.

For example: If field name is username then the method name will be clean_username().

self is the only argument to this method. It takes value from the self.cleaned_data dictionary.

Use this method to do the cleaning, specific to the particular attribute and not the type of the field of the attribute.

For example: There is an attribute username in a Form. Type of this attribute’s field is CharField. Now if we want to check whether the value of the attribute username is unique or not, then, clean_username() method is the right place for it.

Remember, this cleaning has nothing to do with the type of the field of the attribute i.e. CharField.

It should return a value of the same type of that of Field because this value will replace the original value present in the cleaned_data dictionary.

For example: the above mentioned clean_username()must return a value of the type CharField only.

3. Form.clean():

Finally, Form.clean() is called. Similar to clean_<fieldname>(), it is also a Form subclass method. Here, we can perform validations that require to access multiple form attributes. For instance,

  • If field A is present then field B should contain a valid Email address.
  • Field password and re-password should contain equal values.

Since, at this time, all the field validations have already run. Therefore, here we can access form’s errors attribute, to check all the errors raised by the cleaning of individual fields.

Form.clean()raises errors that are not associated to any specific field and so, they are stored in a special field __all__. This field is accessible via non_field_errors() method.

Use the add_error() method to attach errors to particular fields of a form.

Order of execution:

Form.is_valid()executes all the methods explained above in a certain order so as to raise a proper Validation Error at a proper place.

Firstly, Field.clean() and clean_<fieldname>() methods are run for every field in the form in the following order:

  • Field.clean()
    • to_python()
    • validate()
    • run_validators()
  • clean_<fieldname>()

Finally, the common method Form.clean() is run.

Any of these methods can raise a Validation Error in case of supply of invalid data.

Note: For any field, if at any point, Field.clean() raises a Validation Error then any field-specific cleaning method is not called.

For example: If to_python()raises a Validation Error then validate(), run_validators() and clean_<fieldname>() are skipped for that particular field.

However, other fields will still execute their cleaning methods.

This all happens under the hood of Django, during the execution of form and field validation.


Leave a Reply

Your email address will not be published. Required fields are marked *