Django Form Validation State Machine
The Django Form validation process is a state machine that transitions a form from an initial instantiation to a validated state.
A form starts as either Forms and Validation (no data provided) or django.forms.boundfield (data/files provided). The validation process is lazily triggered by accessing the errors property or calling is_valid().
The core of the state machine is the full_clean() method, which orchestrates three main phases:
- Field Cleaning: Each field's
clean()method is called (performingto_python,validate, andrun_validators), followed by any customclean_<fieldname>()methods on the form. - Form Cleaning: The form's
clean()method is called for cross-field validation. - Post Cleaning: An internal hook (
_post_clean()) used primarily byModelFormto perform model-level validation and unique checks.
During these phases, any ValidationError encountered is captured via add_error(), which populates the _errors dictionary and removes the corresponding field from cleaned_data. A form is considered Overview of the Validation API only if it is bound and the _errors collection is empty after cleaning.
Key Architectural Findings:
- Forms are either Unbound (is_bound=False) or Bound (is_bound=True) upon instantiation.
- Validation is lazy: full_clean() is only called when errors or is_valid() are accessed.
- The full_clean() method resets the _errors dictionary and populates cleaned_data.
- Field-level validation involves a sequence: to_python -> validate -> run_validators -> clean_<field>().
- ModelForm extends the state machine via _post_clean() to include model instance validation and unique constraints.
- add_error() is the primary mechanism for state transition to 'Invalid', ensuring cleaned_data is kept in sync by removing failing fields.