How does form handling and validation work in Django?
Learn how Django forms handle binding and validation: is_valid(), cleaned_data, clean methods, ModelForm, and error handling for reliable user input.
Expected Interview Answer
Django forms handle rendering, binding, and validating user input: you define a Form or ModelForm class, bind it to request data, and call is_valid() to run validation, after which cleaned data is available in form.cleaned_data.
An unbound form renders empty fields, while a bound form holds submitted data. Calling is_valid() triggers a three-layer process: each field converts and validates its raw value, per-field clean_<field>() methods run custom checks, and a form-wide clean() validates relationships across fields. Errors collect in form.errors and raise ValidationError, while valid data lands in cleaned_data. A ModelForm derives fields directly from a model and adds a save() method, streamlining create and update flows.
- Automatic HTML rendering and re-population on errors
- Layered validation from field to form level
- Built-in protection like required, max_length, and type coercion
- ModelForm ties forms to models with a save() shortcut
- Clear error reporting through form.errors and cleaned_data
AI Mentor Explanation
A Django form is like the third umpire reviewing a decision. Raw footage (submitted data) comes in, and each check runs in order: is the delivery legal, is the batter in, does everything agree. Field validation is a single-frame check, clean() is cross-checking multiple angles together, and only when every review passes is the decision (cleaned_data) confirmed; otherwise errors are flagged.
Step-by-Step Explanation
Step 1
Define the form class
Create a Form with explicit fields or a ModelForm whose fields derive from a model via Meta.
Step 2
Bind data to the form
Instantiate with request.POST (and request.FILES) to create a bound form holding the submitted values.
Step 3
Call is_valid()
This runs full validation and populates cleaned_data on success or form.errors on failure.
Step 4
Add custom validation
Use clean_<field>() for one field and clean() for cross-field rules, raising ValidationError when invalid.
Step 5
Process or re-render
On success use cleaned_data (or form.save() for a ModelForm); on failure re-render the form to show errors.
What Interviewer Expects
- Difference between bound and unbound forms
- What is_valid() actually does and when cleaned_data appears
- The order of field validation, clean_<field>(), and clean()
- How ModelForm relates to a model and its save() method
- How errors are collected and re-displayed to the user
Common Mistakes
- Accessing cleaned_data before calling is_valid()
- Confusing clean_<field>() with the form-wide clean()
- Forgetting request.FILES for forms with file uploads
- Raising a plain exception instead of ValidationError
- Not re-rendering the bound form so users lose their input on error
Best Answer (HR Friendly)
“Django forms take whatever a user submits and check it against rules you set, like required fields or valid formats, before you trust it. If something is wrong Django collects clear error messages and shows the form again; if everything is valid you get clean, ready-to-use data.”
Code Example
from django import forms
from django.core.exceptions import ValidationError
class SignupForm(forms.Form):
username = forms.CharField(max_length=30)
password = forms.CharField(widget=forms.PasswordInput)
confirm = forms.CharField(widget=forms.PasswordInput)
def clean_username(self):
name = self.cleaned_data['username']
if ' ' in name:
raise ValidationError('Username cannot contain spaces.')
return name
def clean(self):
cleaned = super().clean()
if cleaned.get('password') != cleaned.get('confirm'):
raise ValidationError('Passwords do not match.')
return cleaned
def signup(request):
if request.method == 'POST':
form = SignupForm(request.POST)
if form.is_valid():
data = form.cleaned_data # safe to use now
# ... create the user ...
else:
form = SignupForm() # unbound, empty form
return render(request, 'signup.html', {'form': form})Follow-up Questions
- What is the difference between a Form and a ModelForm?
- In what order do field, clean_<field>(), and clean() run?
- How do you validate two fields against each other?
- How does Django re-populate a form after a validation error?
- Why must you use request.FILES for file uploads?
MCQ Practice
1. Where is validated form data available after successful validation?
After is_valid() returns True, the coerced and validated values are stored in form.cleaned_data.
2. Which method validates relationships across multiple fields?
The form-wide clean() method runs after individual field validation and is the place for cross-field checks.
3. What should you raise when custom validation fails?
Raising ValidationError in clean methods lets Django collect the message into form.errors and re-display it.
Flash Cards
What does is_valid() do? — Runs full validation, populating cleaned_data on success or form.errors on failure.
clean_<field>() vs clean()? — clean_<field>() validates one field; clean() validates across multiple fields.
What is a bound form? — A form instantiated with submitted data, ready to validate and show errors.
What does a ModelForm add? — Fields derived from a model plus a save() method to create or update instances.