Django

Django Admin Customization👨‍💻

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.

Key Takeaways

  • 1ModelAdmin is the central class for admin customization — list_display, list_filter, search_fields, and fieldsets control the list view and change form
  • 2Custom admin actions let you perform bulk operations (publish, export, archive) on selected objects directly from the change list
  • 3TabularInline and StackedInline embed related models inside the parent's change form, eliminating the need to navigate between pages
  • 4Custom admin views extend the admin with entirely new pages (dashboards, reports) while preserving authentication and the admin layout
  • 5Django 6+ introduces Font Awesome icons, password_change_form customization, and distinct message level icons for a more polished admin experience
  • 6Permission methods (has_add_permission, has_change_permission, has_delete_permission) provide fine-grained per-object access control

Master django admin customization

Take the Django Admin Mastery course with hands-on lessons and challenges.

Examples

ModelAdmin with list_display, list_filter, and search_fields

python

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.

Custom admin action for bulk operations

python

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 and StackedInline for related models

python

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 admin view with admin_view wrapper

python

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.).

Custom AdminSite with Django 6+ features

python

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.

Common Mistakes

Mistake:

Including a field in both list_display_links and list_editable — Django requires the link field to remain non-editable

Fix:

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'].

Mistake:

Defining custom display methods or computed columns without @admin.display(ordering=...), making the column unsortable

Fix:

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.

Mistake:

Placing custom URLs after super().get_urls() in get_urls(), causing Django's catch-all pattern to match first

Fix:

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.

Mistake:

Accessing ForeignKey fields in list_display without list_select_related, causing N+1 queries on every page load

Fix:

Set list_select_related = ['author', 'category'] or override get_queryset() with select_related() to load related objects in a single query.

Best Practices

  • Always set list_display with 4-6 key fields — the default single-column __str__ view is nearly useless for identifying records
  • Use fieldsets with 'collapse' classes for rarely-used sections to keep the change form focused and scannable
  • Call message_user() after every admin action to provide clear feedback — silent actions confuse administrators
  • Wrap custom admin views with self.admin_site.admin_view() to enforce authentication and permission checks automatically
  • Use autocomplete_fields instead of raw_id_fields for ForeignKey lookups — it provides a better UX with search-as-you-type functionality
  • Set list_per_page to 25-50 instead of the default 100 to improve page load times for complex querysets

Summary

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.

Practice Django with hands-on challenges

Learn django admin customization hands-on in your IDE

Interactive lessons and challenges on Stanza, practice in VS Code, Cursor, or the web.

Related Concepts

Related Cheatsheets

Master Django with Stanza

Interactive lessons and challenges, right in your code editor.

Check the free courses. No credit card.