Django's admin interface is one of the framework's most powerful features — a fully functional CRUD interface generated automatically from your models. Out of the box it works, but it looks generic and lacks the workflows your team actually needs. The real power comes from customizing it: controlling which columns appear, adding bulk actions, embedding related models inline, and even building entirely custom views within the admin.
With Django 6+, the admin has gained Font Awesome icons for a more polished UI, password_change_form customization on AdminSite, and distinct message level icons that visually differentiate success, warning, and error messages. These improvements make a customized admin feel less like a scaffolded tool and more like a purpose-built back office.
Master django admin customization
Take the Django Admin Mastery course with hands-on lessons and challenges.
A complete ModelAdmin setup covering the most common options. list_display defines the columns shown in the change list. list_filter adds sidebar filters (RelatedOnlyFieldListFilter shows only authors that have articles). search_fields enables the search box with double-underscore lookups for related models. fieldsets organize the change form into collapsible sections.
Admin actions receive the ModelAdmin, the request, and a queryset of selected objects. The make_published action uses queryset.update() for efficient bulk updates and calls message_user() to provide feedback. The export_as_csv action returns an HttpResponse with CSV content, causing a file download. Always call select_related() when accessing related fields to avoid N+1 queries.
TabularInline renders related objects as table rows — ideal for line items where each record has a few fields. StackedInline renders each related object as a full form — better for complex records with many fields. Use extra to control how many blank forms appear, min_num/max_num to enforce cardinality, and autocomplete_fields to replace dropdowns with search widgets for ForeignKey fields.
Custom views extend the admin with pages that don't map to CRUD operations — dashboards, reports, import wizards. Wrapping with self.admin_site.admin_view() ensures the view requires admin authentication and has permission checks. Custom URLs must be prepended before the default URLs so they are matched first. Use each_context() to get the standard admin template variables (site_header, has_permission, etc.).
A custom AdminSite lets you override site-wide settings like the header, title, and branding. Django 6+ adds the password_change_form attribute for customizing the password change page. You can also inject extra context into every admin page via each_context(). Register models with custom_admin.register() instead of admin.site.register() to use your custom site.
Including a field in both list_display_links and list_editable — Django requires the link field to remain non-editable
Set list_display_links to a different field first, then add the desired field to list_editable. For example, use list_display_links = ['id'] and list_editable = ['status', 'title'].
Defining custom display methods or computed columns without @admin.display(ordering=...), making the column unsortable
Always add the ordering parameter pointing to a real database field: @admin.display(description='Status', ordering='status'). This lets users click the column header to sort.
Placing custom URLs after super().get_urls() in get_urls(), causing Django's catch-all pattern to match first
Always prepend custom URLs: return custom_urls + urls. Django's default URL patterns include catch-all routes that will intercept your custom paths if they come first.
Accessing ForeignKey fields in list_display without list_select_related, causing N+1 queries on every page load
Set list_select_related = ['author', 'category'] or override get_queryset() with select_related() to load related objects in a single query.
Django admin customization revolves around the ModelAdmin class, which controls list views (list_display, list_filter, search_fields), change forms (fieldsets, readonly_fields), and bulk operations (admin actions). TabularInline and StackedInline embed related models for seamless editing. Custom views extend the admin with dashboards and reports. Django 6+ improves the experience with Font Awesome icons, password_change_form customization, and distinct message level icons. The key principle: configure the admin to match your team's workflow rather than forcing users to adapt to the defaults.
Interactive lessons and challenges on Stanza, practice in VS Code, Cursor, or the web.
Interactive lessons and challenges, right in your code editor.
Check the free courses. No credit card.