Skip to main content

Django Admin Inlines

Introduction

Django Admin is a powerful built-in feature that automatically generates an admin interface for your models. One of its most useful capabilities is inlines - a feature that allows you to edit related models on the same page. For example, if you have a Book model with multiple Chapter objects related to it, inlines let you edit both the book and its chapters from a single admin page.

This feature significantly improves productivity by:

  • Reducing navigation between different admin pages
  • Providing a clearer view of related data
  • Allowing for faster data entry and editing

In this tutorial, we'll explore Django Admin Inlines, understand their types, and see how to implement them in real-world applications.

Understanding Model Relationships

Before diving into inlines, let's quickly refresh our understanding of model relationships in Django:

  1. One-to-Many (ForeignKey): One model is related to multiple instances of another model
  2. Many-to-Many (ManyToManyField): Multiple instances of one model relate to multiple instances of another
  3. One-to-One (OneToOneField): One model instance relates to exactly one instance of another model

Inlines are most commonly used with One-to-Many relationships, though they work with other relationship types as well.

Types of Inlines

Django offers two main types of inlines:

  1. TabularInline: Displays related objects in a table format (compact, row-based)
  2. StackedInline: Shows related objects in a stacked form layout (more detailed, form-like)

Let's see how to implement both.

Basic Inline Setup

Let's start with a common example: an Author with multiple Books. First, we'll define our models:

python
# models.py
from django.db import models

class Author(models.Model):
name = models.CharField(max_length=100)
bio = models.TextField(blank=True)

def __str__(self):
return self.name

class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')
publication_date = models.DateField()
isbn = models.CharField(max_length=13)

def __str__(self):
return self.title

Now, to display books as inlines within the Author admin page, we need to set up the admin:

python
# admin.py
from django.contrib import admin
from .models import Author, Book

class BookInline(admin.TabularInline):
model = Book
extra = 1 # Number of empty forms to display

class AuthorAdmin(admin.ModelAdmin):
inlines = [BookInline]
list_display = ('name',)

admin.site.register(Author, AuthorAdmin)
admin.site.register(Book) # Register Book separately too

With this setup, when you edit an Author, you'll see a table at the bottom of the page with all related Books and a form to add new ones.

TabularInline vs StackedInline

Let's compare both inline types using our Author-Book example:

TabularInline (Table Format)

python
class BookInline(admin.TabularInline):
model = Book
extra = 1

This displays books in a compact table format, with each book as a row and fields as columns. It's ideal when you have many related objects or when the related model has few fields.

StackedInline (Stacked Format)

python
class BookInline(admin.StackedInline):
model = Book
extra = 1

This displays each book in the same format as a standalone model form - with fields stacked vertically. It's more readable for related models with many fields but takes up more vertical space.

Advanced Inline Configuration

Django provides several options to customize inlines:

Controlling Number of Forms

python
class BookInline(admin.TabularInline):
model = Book
extra = 2 # Show 2 empty forms for adding new books
max_num = 10 # Maximum number of forms
min_num = 1 # Minimum number of forms

Displaying Specific Fields

python
class BookInline(admin.TabularInline):
model = Book
fields = ['title', 'publication_date'] # Only show these fields

Adding Fieldsets (for StackedInline)

python
class BookInline(admin.StackedInline):
model = Book
fieldsets = [
('Basic Information', {'fields': ['title', 'isbn']}),
('Publication Details', {'fields': ['publication_date']})
]

Customizing Display

python
class BookInline(admin.TabularInline):
model = Book
readonly_fields = ['isbn'] # Make ISBN read-only
show_change_link = True # Add link to change the related object

Real-World Example: Blog System

Let's implement a more complex real-world example: a blog system with posts and comments.

python
# models.py
from django.db import models
from django.contrib.auth.models import User

class BlogPost(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
published_date = models.DateTimeField(auto_now_add=True)

def __str__(self):
return self.title

class Comment(models.Model):
post = models.ForeignKey(BlogPost, on_delete=models.CASCADE, related_name='comments')
author_name = models.CharField(max_length=100)
text = models.TextField()
created_date = models.DateTimeField(auto_now_add=True)
approved = models.BooleanField(default=False)

def __str__(self):
return f"Comment by {self.author_name}"

class Tag(models.Model):
name = models.CharField(max_length=50, unique=True)
posts = models.ManyToManyField(BlogPost, related_name='tags')

def __str__(self):
return self.name

Now, let's set up the admin with inlines:

python
# admin.py
from django.contrib import admin
from .models import BlogPost, Comment, Tag

class CommentInline(admin.TabularInline):
model = Comment
extra = 1
readonly_fields = ['created_date']
fields = ['author_name', 'text', 'approved', 'created_date']

class TagInline(admin.TabularInline):
model = Tag.posts.through
extra = 1
verbose_name = "Tag"
verbose_name_plural = "Tags"

class BlogPostAdmin(admin.ModelAdmin):
inlines = [CommentInline, TagInline]
list_display = ('title', 'author', 'published_date', 'comment_count')
search_fields = ['title', 'content']

def comment_count(self, obj):
return obj.comments.count()
comment_count.short_description = "Number of comments"

admin.site.register(BlogPost, BlogPostAdmin)
admin.site.register(Comment)
admin.site.register(Tag)

This example demonstrates:

  • Multiple inlines on a single admin page (Comments and Tags)
  • Using inlines with both ForeignKey and ManyToManyField relationships
  • Custom verbose names for better readability
  • Read-only fields in inlines
  • Custom methods in the admin class

Working with Many-to-Many Relationships

For Many-to-Many relationships, Django uses a special approach. In our example above, we used Tag.posts.through which refers to the intermediate model Django creates for the Many-to-Many relationship.

Nested Inlines

Sometimes you might want to show multiple levels of related models. While Django's admin doesn't natively support nested inlines, there are third-party packages like django-nested-admin that enable this functionality.

Here's how you might set it up:

bash
pip install django-nested-admin

Add to your INSTALLED_APPS:

python
INSTALLED_APPS = [
# ...
'nested_admin',
# ...
]

Then implement nested inlines:

python
# admin.py
import nested_admin

class SubItemInline(nested_admin.NestedTabularInline):
model = SubItem
extra = 1

class ItemInline(nested_admin.NestedTabularInline):
model = Item
extra = 1
inlines = [SubItemInline]

class CategoryAdmin(nested_admin.NestedModelAdmin):
inlines = [ItemInline]

admin.site.register(Category, CategoryAdmin)

Best Practices for Inlines

  1. Use TabularInline for compact data: For related objects with few fields, use TabularInline to conserve space

  2. Use StackedInline for complex forms: When related objects have many fields, StackedInline provides better readability

  3. Limit the number of inlines: Too many inlines on one page can make the form slow and unwieldy. Use max_num to limit them

  4. Consider performance: Inlines load all related objects at once, which can be slow if there are many. Consider using filters or limiting displayed fields

  5. Use fieldsets to organize: Especially with StackedInline, use fieldsets to group related fields

  6. Consider read-only fields: For important fields that shouldn't be edited in the inline context

Summary

Django Admin Inlines are a powerful feature that lets you edit related models from a single admin page, improving workflow and data entry efficiency. We've covered:

  • Basic inline setup with TabularInline and StackedInline
  • Advanced configuration options
  • Real-world examples with different relationship types
  • Best practices for using inlines effectively

By leveraging inlines, you can create a much more intuitive and efficient admin interface for your Django projects. This is particularly useful when working with models that have strong logical relationships.

Additional Resources

Exercises

  1. Create a simple Product and ProductImage model where each Product can have multiple images, and implement inline editing.

  2. Extend the blog system example by adding Categories and implementing both TabularInline and StackedInline to compare their layouts.

  3. Try implementing a nested inline structure using django-nested-admin for a hierarchical data model (e.g., Courses > Modules > Lessons).

  4. Create a custom inline that validates related models (hint: you'll need to override the clean() method).



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)