Django Model Forms provide a convenient way to create forms directly from Django models. They connect a form with a database model and can simplify creating and updating database records.
Instead of defining every form field manually, a ModelForm can generate form fields based on the fields defined in a model.
A ModelForm is a Django form that is connected to a model.
For example, if you have a Student model containing:
name
email
mobile
course
A ModelForm can automatically create corresponding form fields for these model fields.
ModelForm reduces the amount of code required to create forms connected to database models.
ModelForm is available through Django's forms module.
from django import forms
You can then create a class that inherits from
forms.ModelForm.
Suppose we have the following Student model:
from django.db import models
class Student(models.Model):
name = models.CharField(
max_length=100
)
email = models.EmailField()
mobile = models.CharField(
max_length=15
)
age = models.IntegerField()
def __str__(self):
return self.name
A ModelForm can be created from this model.
Create a form class using forms.ModelForm.
from django import forms
from .models import Student
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = [
"name",
"email",
"mobile",
"age"
]
Django will generate form fields based on the selected model fields.
The inner Meta class provides configuration information for
the ModelForm.
class Meta:
model = Student
fields = [
"name",
"email"
]
It tells Django which model the form is connected to and which model fields should be included.
The fields option specifies which model fields should appear in
the form.
class Meta:
model = Student
fields = [
"name",
"email"
]
Only Name and Email will be included in the generated form.
You can include all model fields using "__all__".
class Meta:
model = Student
fields = "__all__"
This tells Django to include all editable model fields in the form.
The exclude option can be used to leave specific model fields
out of the form.
class Meta:
model = Student
exclude = [
"age"
]
The Age field will not be included in the generated form.
Pass the ModelForm to a template from the view.
return render(
request,
"student_form.html",
{"form": form}
)
Then render the form:
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">
Save
</button>
</form>
A ModelForm can save submitted data directly into the database.
if form.is_valid():
form.save()
The save() method creates a database record when the form is
used without an existing instance.
from django.shortcuts import render
from .forms import StudentForm
def student_create(request):
if request.method == "POST":
form = StudentForm(
request.POST
)
if form.is_valid():
form.save()
else:
form = StudentForm()
return render(
request,
"student_form.html",
{"form": form}
)
The form is displayed for GET requests and processed for POST requests.
After successfully saving a record, redirecting to another page can prevent duplicate form submissions.
from django.shortcuts import (
render,
redirect
)
if form.is_valid():
form.save()
return redirect(
"student_list"
)
This is commonly used after successful POST requests.
A ModelForm can also update an existing model instance.
student = Student.objects.get(
id=1
)
form = StudentForm(
instance=student
)
The existing student's values are displayed in the form.
When processing submitted data for an existing record, pass the same instance to the ModelForm.
form = StudentForm(
request.POST,
instance=student
)
if form.is_valid():
form.save()
Django updates the existing record instead of creating a new one.
| Operation | ModelForm |
|---|---|
| Create | StudentForm(request.POST) |
| Update | StudentForm(request.POST, instance=student) |
The instance argument is the important difference when updating
an existing record.
ModelForms use Django's form validation system and model field information to validate submitted data.
if form.is_valid():
form.save()
For example, an EmailField can validate email input and required fields can reject empty values.
After successful validation, cleaned values are available through
cleaned_data.
if form.is_valid():
name = form.cleaned_data[
"name"
]
email = form.cleaned_data[
"email"
]
This is useful when additional processing is required before saving.
You can override a generated ModelForm field when you need additional control.
class StudentForm(forms.ModelForm):
name = forms.CharField(
max_length=100,
label="Student Name"
)
class Meta:
model = Student
fields = [
"name",
"email",
"mobile"
]
The custom field replaces the automatically generated field.
Widgets can be customized in a ModelForm.
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = [
"name",
"email"
]
widgets = {
"name": forms.TextInput(
attrs={
"class": "form-control"
}
),
"email": forms.EmailInput(
attrs={
"class": "form-control"
}
)
}
This allows you to add CSS classes and other HTML attributes.
Labels can be customized using the labels option.
class Meta:
model = Student
fields = [
"name",
"email"
]
labels = {
"name": "Student Name",
"email": "Email Address"
}
The help_texts option can provide additional information to
users.
class Meta:
model = Student
fields = [
"name",
"email"
]
help_texts = {
"name":
"Enter your full name.",
"email":
"Enter a valid email address."
}
You can define a clean_<fieldname>() method to add custom
validation.
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = [
"name",
"email"
]
def clean_name(self):
name = self.cleaned_data[
"name"
]
if len(name) < 3:
raise forms.ValidationError(
"Name must contain at least 3 characters."
)
return name
A ModelForm can include relationship fields such as ForeignKey.
class Student(models.Model):
name = models.CharField(
max_length=100
)
course = models.ForeignKey(
Course,
on_delete=models.CASCADE
)
The ModelForm can include the Course field:
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = [
"name",
"course"
]
Django can generate a field for selecting the related Course objects.
ModelForms can also include ManyToManyField relationships.
class Student(models.Model):
name = models.CharField(
max_length=100
)
courses = models.ManyToManyField(
Course
)
The ModelForm can include:
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = [
"name",
"courses"
]
Not every model field should necessarily be exposed to users through a form.
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = [
"name",
"email"
]
Explicitly selecting fields helps control which model data users can edit.
When updating records, get_object_or_404() can be used to safely
retrieve the object.
from django.shortcuts import (
render,
redirect,
get_object_or_404
)
def student_edit(request, id):
student = get_object_or_404(
Student,
id=id
)
if request.method == "POST":
form = StudentForm(
request.POST,
instance=student
)
if form.is_valid():
form.save()
return redirect(
"student_list"
)
else:
form = StudentForm(
instance=student
)
return render(
request,
"student_edit.html",
{"form": form}
)
models.py
from django.db import models
class Student(models.Model):
name = models.CharField(
max_length=100
)
email = models.EmailField()
mobile = models.CharField(
max_length=15
)
course = models.CharField(
max_length=100
)
def __str__(self):
return self.name
forms.py
from django import forms
from .models import Student
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = [
"name",
"email",
"mobile",
"course"
]
views.py
from django.shortcuts import (
render,
redirect
)
from .forms import StudentForm
def student_create(request):
if request.method == "POST":
form = StudentForm(
request.POST
)
if form.is_valid():
form.save()
return redirect(
"student_list"
)
else:
form = StudentForm()
return render(
request,
"student_form.html",
{"form": form}
)
student_form.html
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">
Save Student
</button>
</form>
forms.ModelForm.Meta class.model.fields or exclude.request.POST while processing submitted data.{% csrf_token %} in POST forms.form.is_valid().form.save() after successful validation.instance when updating an existing record.ModelForm is one of the most useful Django features for creating database forms.
Meta.model specifies the model.Meta.fields specifies fields included in the form.fields = "__all__" includes all editable model fields.form.save() can create a database record.instance argument is used when updating records.ModelForm connects Django forms with models.forms.ModelForm to create a ModelForm.Meta class defines model and form configuration.fields controls which model fields appear.form.save() can create or update database records.instance when updating an existing object.Question: Which class is used to create a Django ModelForm?