Inline allows you to edit related objects directly on the parent object’s page.
TabularInline
from django.contrib import admin
from .models import Project, Task
class TaskInline(admin.TabularInline):
model = Task
extra = 1 # number of empty forms
fields = ['title', 'status', 'priority']
@admin.register(Project)
class ProjectAdmin(admin.ModelAdmin):
inlines = [TaskInline]
Result: a table of tasks will appear on the project page.
StackedInline
class TaskInline(admin.StackedInline):
model = Task
extra = 0
fields = ['title', 'description', 'status']
show_change_link = True # link to the edit page
StackedInline displays each object as a block; TabularInline displays each object as a table row.
Inline Settings
class TaskInline(admin.TabularInline):
model = Task
extra = 0
max_num = 10 # maximum number of objects
min_num = 1 # minimum
can_delete = True
readonly_fields = ['created_at']
extra = 0 — Remove Empty Forms
By default extra = 3 — Django shows three empty forms for adding new objects. This often clutters the interface. Set extra = 0 when users rarely add related objects:
class TaskInline(admin.TabularInline):
model = Task
extra = 0 # no empty forms — add via the "Add another" button
can_delete = False — Prevent Deletion
If deleting related objects through Admin is undesirable — disable the delete checkboxes:
class TaskInline(admin.TabularInline):
model = Task
extra = 0
can_delete = False # removes the "Delete" checkbox column
Useful when tasks should only be deleted through a separate interface or via soft delete.
max_num — Limit the Count
max_num limits how many related objects can be added through the inline. Once the limit is reached, the “Add another” button disappears:
class TaskInline(admin.TabularInline):
model = Task
extra = 0
max_num = 5 # no more than 5 tasks per project through this interface
readonly_fields in Inline
Works the same as in a regular ModelAdmin. Useful for fields like created_at, slug, or computed values:
class TaskInline(admin.TabularInline):
model = Task
extra = 0
fields = ['title', 'status', 'created_at']
readonly_fields = ['created_at']
Fields listed in readonly_fields must also appear in fields, otherwise they won’t be shown.
Inline for ManyToMany
class TagInline(admin.TabularInline):
model = Task.tags.through # intermediate table
extra = 1
Common Mistake: Wrong Direction of the Relation
Inline is registered on the parent model — the one that the other model’s ForeignKey points to.
class Task(models.Model):
project = models.ForeignKey(Project, on_delete=models.CASCADE)
Here Task points to Project. So TaskInline goes inside ProjectAdmin — not the other way around:
# CORRECT: TaskInline inside ProjectAdmin
@admin.register(Project)
class ProjectAdmin(admin.ModelAdmin):
inlines = [TaskInline]
# WRONG: can't put ProjectInline in TaskAdmin with FK on Project
# Django will raise an error: the inline model must have a FK on the parent model
If you need to edit the project from the task page — use raw_id_fields or autocomplete_fields, but not an inline in the reverse direction.
💬 Comments (0)
No comments yet
Be the first to share your opinion about this article!