SyntaxStudy
Sign Up
Django Admin Actions and Inlines
Django Beginner 1 min read

Admin Actions and Inlines

Admin actions are functions that perform an operation on a selected set of objects in the admin list view. Django includes a delete_selected action by default. You can add custom actions — for example "Mark as published" or "Export to CSV" — by defining a function that accepts the ModelAdmin instance, the request, and a QuerySet of selected objects. Actions are registered on the ModelAdmin with the actions attribute. Admin inlines let you edit related model instances on the same admin page as their parent. TabularInline displays related objects in a compact table format, while StackedInline uses a more spacious stacked layout. You define an inline class specifying the related model and add it to the parent ModelAdmin's inlines list. This is ideal for one-to-many relationships like editing a post's images or a product's variants on the same page. The fieldsets attribute on ModelAdmin controls the layout of the add/change form by grouping fields into named sections. Each fieldset is a two-tuple of the section title and a dictionary with a fields key. You can collapse sections by adding 'collapse' to the classes list, which is useful for less frequently edited fields. The readonly_fields attribute marks fields as read-only in the form, useful for auto-generated or computed values.
Example
# blog/admin.py — actions, inlines, and fieldsets
from django.contrib import admin
from django.utils import timezone
from .models import Post, Comment


# --- Inline for comments ---
class CommentInline(admin.TabularInline):
    model       = Comment
    extra       = 0
    readonly_fields = ['author', 'body', 'created_at']
    can_delete  = True


# --- Custom admin action ---
@admin.action(description='Mark selected posts as published')
def make_published(modeladmin, request, queryset):
    updated = queryset.update(status=Post.STATUS_PUBLISHED, published_at=timezone.now())
    modeladmin.message_user(request, f'{updated} post(s) marked as published.')


@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    actions  = [make_published]
    inlines  = [CommentInline]

    fieldsets = (
        (None, {
            'fields': ('title', 'slug', 'author', 'category', 'tags'),
        }),
        ('Content', {
            'fields': ('body', 'cover_img'),
        }),
        ('Publishing', {
            'classes': ('collapse',),
            'fields':  ('status', 'published_at'),
        }),
    )

    readonly_fields = ['created_at', 'updated_at']