Django Forms
Almost every website needs to collect data from users — registration forms, login forms, search boxes, contact forms. Django has a powerful built-in Forms system that handles creating HTML form fields, validating the submitted data, and showing error messages automatically.
What is a Django Form?
A Django Form is a Python class that defines what fields a form should have, what type of data each field accepts, and what rules the data must follow before being accepted. Django then renders these fields as HTML automatically and validates the submitted data for you.
Example: Imagine a bank's account opening form. A teller hands you the form (Django renders the HTML fields), you fill it in (user enters data), and the bank clerk checks each field — is the phone number valid? Is the date of birth in the right format? Is the PAN number filled in? (Django validation). If something is wrong, the clerk hands the form back with errors marked in red (Django shows error messages).
Types of Django Forms
- forms.Form — A manually defined form, not connected to any database model. Good for contact forms, search forms, or custom use cases.
- forms.ModelForm — A form automatically built from a model. If you have a Student model, Django can generate a form from it automatically, saving a lot of repetition.
Creating a Basic Form (forms.Form)
Create a new file called forms.py inside your app folder and define your form class:
# students/forms.py
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(max_length=100)
email = forms.EmailField()
message = forms.CharField(widget=forms.Textarea)
subject = forms.CharField(max_length=200, required=False)
Each attribute here is a form field. Django uses the field type to decide what HTML input to render and how to validate it.
Common Form Field Types
CharField— A single-line text input (renders as<input type="text">)EmailField— Validates that the value looks like an email addressIntegerField— Accepts whole numbers onlyBooleanField— Renders as a checkboxChoiceField— Renders as a dropdown selectDateField— Accepts a date in the correct formatFileField— Accepts a file upload
Using a Form in a View
Your view handles both showing the empty form (GET request) and processing the submitted form (POST request):
# students/views.py
from django.shortcuts import render
from .forms import ContactForm
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST) # Bind submitted data to the form
if form.is_valid(): # Check if all fields are valid
name = form.cleaned_data['name']
message = form.cleaned_data['message']
# Do something with the data (save to DB, send email, etc.)
return render(request, 'students/success.html', {'name': name})
else:
form = ContactForm() # Create an empty form for GET request
return render(request, 'students/contact.html', {'form': form})
Key points in this view:
ContactForm(request.POST)— Creates a "bound" form with the submitted data.form.is_valid()— Returns True if all fields pass validation; False if any field has an error.form.cleaned_data— A dictionary of the cleaned (safe, validated) data. Always use this, not rawrequest.POST.
Example: is_valid() is like a security scanner at the airport. Before you board the plane (save data), everything goes through the scanner (validation). If anything suspicious is found (invalid data), you are stopped and told what needs to be fixed.Displaying the Form in a Template
In your template, display the form using Django's template syntax:
<!-- students/templates/students/contact.html -->
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Send Message</button>
</form>
{% csrf_token %}— Must always be included inside every POST form. It protects your form from CSRF attacks (a type of security threat). Django will reject the form if this token is missing.{{ form.as_p }}— Renders each form field wrapped in a<p>tag automatically.
Other Form Rendering Options
{{ form.as_p }} <-- Each field in a <p> tag
{{ form.as_ul }} <-- Each field in a <li> tag
{{ form.as_table }} <-- Each field in a <tr> tag
Rendering Fields Individually
For more control over layout, you can render each field individually:
<form method="POST">
{% csrf_token %}
<label>Name</label>
{{ form.name }}
{{ form.name.errors }}
<label>Email</label>
{{ form.email }}
{{ form.email.errors }}
<button type="submit">Submit</button>
</form>
Form Validation — Built-in and Custom
Django automatically validates fields based on their type. But you can also add your own custom validation rules.
Field-level custom validation
Add a method called clean_fieldname() to validate a specific field:
class ContactForm(forms.Form):
name = forms.CharField(max_length=100)
roll_number = forms.IntegerField()
def clean_roll_number(self):
roll = self.cleaned_data['roll_number']
if roll <= 0:
raise forms.ValidationError("Roll number must be a positive number.")
return roll
Example: Built-in validation catches obvious errors — "this field is required" or "enter a valid email". Custom validation catches your specific business rules — "roll number must be between 1 and 500" or "username cannot contain spaces".
ModelForm — Building a Form from a Model
If you already have a model, you don't need to rewrite all the same fields in a form. Use ModelForm to generate the form automatically from the model:
# students/forms.py
from django import forms
from .models import Student
class StudentForm(forms.ModelForm):
class Meta:
model = Student # Use the Student model
fields = ['name', 'roll_number', 'email'] # Show only these fields
# OR use fields = '__all__' to include all fields
The view for a ModelForm works the same way, but saving is even easier:
# students/views.py
from .forms import StudentForm
def add_student(request):
if request.method == 'POST':
form = StudentForm(request.POST)
if form.is_valid():
form.save() # <-- Saves directly to the database!
return render(request, 'students/success.html')
else:
form = StudentForm()
return render(request, 'students/add_student.html', {'form': form})
form.save() creates a new record in the database with the submitted data in one single line.
Example: ModelForm is like a pre-filled job application form generated from the HR department's requirements list. You don't design it from scratch — it's automatically created based on what the HR system (model) needs. One click saves the application directly to the HR database.
Quick Recap
- Django Forms handle creating HTML fields, validating data, and displaying errors automatically.
- Use
forms.Formfor custom forms andforms.ModelFormfor forms based on a model. - Always include
{% csrf_token %}inside every POST form template. - Check
form.is_valid()before processing submitted data. - Always use
form.cleaned_datato access validated form data — never use rawrequest.POSTdata directly. - Use
form.save()in a ModelForm to save data directly to the database in one line.
