Django Model Forms
Creating forms directly from database models
🗄️ What are Model Forms?
Model Forms automatically create forms from your database models. They save time by generating form fields from model fields and handle saving data to the database automatically.
# forms.py - Create form from model
from django import forms
from .models import Article
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ['title', 'content', 'author']
Model Form Benefits
Auto-Generation
Fields created from model
Easy Saving
Direct database save
Built-in Validation
Model constraints applied
Update Support
Edit existing records
🔹 Creating a Model
First, define your database model. Models represent database tables with fields defining the data structure and types for each column.
# models.py
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
isbn = models.CharField(max_length=13, unique=True)
published_date = models.DateField()
pages = models.IntegerField()
description = models.TextField()
def __str__(self):
return self.title
🔹 Creating a Model Form
ModelForm automatically generates form fields from your model. Specify which fields to include or exclude using the Meta class configuration options.
# forms.py
from django import forms
from .models import Book
class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = ['title', 'author', 'isbn',
'published_date', 'pages', 'description']
# OR exclude specific fields
# exclude = ['id']
# OR include all fields
# fields = '__all__'
# Custom labels
labels = {
'isbn': 'ISBN Number',
'published_date': 'Publication Date'
}
# Custom widgets
widgets = {
'description': forms.Textarea(attrs={'rows': 4}),
'published_date': forms.DateInput(attrs={'type': 'date'})
}
🔹 Using Model Forms in Views
Model forms simplify view logic with built-in save functionality. Handle both creating new records and updating existing ones with minimal code.
# views.py
from django.shortcuts import render, redirect
from .forms import BookForm
def add_book(request):
if request.method == 'POST':
form = BookForm(request.POST)
if form.is_valid():
form.save() # Automatically saves to database
return redirect('book_list')
else:
form = BookForm()
return render(request, 'add_book.html', {'form': form})
# Edit existing book
def edit_book(request, book_id):
book = Book.objects.get(id=book_id)
if request.method == 'POST':
form = BookForm(request.POST, instance=book)
if form.is_valid():
form.save()
return redirect('book_detail', book_id=book.id)
else:
form = BookForm(instance=book)
return render(request, 'edit_book.html', {'form': form})
🔹 Customizing Model Forms
Override form methods to add custom validation or modify data before saving. Use clean methods for field-specific or form-wide validation logic.
# forms.py
from django import forms
from .models import Book
class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = '__all__'
# Custom field validation
def clean_pages(self):
pages = self.cleaned_data.get('pages')
if pages < 1:
raise forms.ValidationError('Pages must be positive')
return pages
# Custom form validation
def clean(self):
cleaned_data = super().clean()
title = cleaned_data.get('title')
author = cleaned_data.get('author')
# Check for duplicate
if Book.objects.filter(title=title, author=author).exists():
raise forms.ValidationError('This book already exists')
return cleaned_data
# Modify before saving
def save(self, commit=True):
book = super().save(commit=False)
book.title = book.title.title() # Capitalize
if commit:
book.save()
return book
🔹 Partial Updates
Update only specific fields without requiring all form data. Useful for forms that modify a subset of model fields.
# forms.py - Form with limited fields
class BookUpdateForm(forms.ModelForm):
class Meta:
model = Book
fields = ['title', 'description'] # Only these fields
# views.py
def quick_edit(request, book_id):
book = Book.objects.get(id=book_id)
form = BookUpdateForm(request.POST or None, instance=book)
if form.is_valid():
form.save() # Only updates title and description
return redirect('book_detail', book_id=book.id)
return render(request, 'quick_edit.html', {'form': form})