Django Forms
Django forms build the HTML inputs, check the submitted data and show errors, all from one Python class.
A Simple Form Class
Create courses/forms.py:
Example
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(max_length=50)
email = forms.EmailField()
message = forms.CharField(widget=forms.Textarea)
def clean_name(self):
name = self.cleaned_data["name"].strip()
if len(name) < 3:
raise forms.ValidationError("Name must be at least 3 letters.")
return nameA method named clean_<field> adds your own check for that field.
The View
Example
from django.shortcuts import render, redirect
from .forms import ContactForm
def contact(request):
if request.method == "POST":
form = ContactForm(request.POST)
if form.is_valid():
name = form.cleaned_data["name"]
# send an email or save the message here
return redirect("thanks")
else:
form = ContactForm()
return render(request, "courses/contact.html", {"form": form})The flow:
- First visit (GET): show an empty form.
- The visitor submits (POST): fill the form with
request.POST. is_valid()runs all checks. Clean values go intocleaned_data.- If valid, do the work and redirect. If not, show the form again with errors.
The Template
Example
<h1>Contact Us</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Send</button>
</form>{% csrf_token %}adds a hidden security token. Django rejects POST forms without it.{{ form.as_p }}prints every field with its label, each in a paragraph.
If a visitor submits the name "Al" and an invalid email, the form comes back showing:
Name must be at least 3 letters. Enter a valid email address.
Never skip {% csrf_token %}. It stops other websites from sending forms to your site using your visitor's login (a CSRF attack).
Common Form Fields
| Field | HTML input |
|---|---|
CharField | Text box |
CharField(widget=forms.Textarea) | Multi-line text |
EmailField | Email box with email validation |
IntegerField | Number box |
BooleanField(required=False) | Checkbox |
ChoiceField(choices=...) | Drop-down list |
DateField | Date |
ModelForm: Forms from Models
When a form saves to a model, a ModelForm builds the fields from the model for you:
Example
from django import forms
from .models import Student
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = ["name", "email", "course"]Example
from django.shortcuts import render, redirect
from .forms import StudentForm
def register(request):
form = StudentForm(request.POST or None)
if request.method == "POST" and form.is_valid():
student = form.save()
return redirect("course-detail", course_id=student.course.id)
return render(request, "courses/register.html", {"form": form})form.save() creates the Student row in the database. The course field automatically becomes a drop-down of all courses, and unique=True on email is checked for you.
Editing an Existing Row
Pass instance= to fill the form with an existing object:
Example
from django.shortcuts import get_object_or_404
def edit_student(request, pk):
student = get_object_or_404(Student, pk=pk)
form = StudentForm(request.POST or None, instance=student)
if request.method == "POST" and form.is_valid():
form.save()
return redirect("course-list")
return render(request, "courses/register.html", {"form": form})Exercise
Exercise
Where does Django put the checked, cleaned values after form.is_valid() returns True?
