SyntaxStudy
Sign Up
Django Customising the Admin Site and Overriding Templates
Django Beginner 1 min read

Customising the Admin Site and Overriding Templates

Django allows you to customise the admin site at multiple levels. The simplest customisations are setting admin.site.site_header, admin.site.site_title, and admin.site.index_title to change the branding of the admin interface. These attributes are typically set in the app's admin.py or in AppConfig.ready(). You can also create a custom AdminSite subclass to have multiple separate admin interfaces with different registered models. You can override any admin template by creating a file with the same path in your project's templates/admin/ directory. Django searches project template directories before the admin app's own templates. For example, creating templates/admin/base_site.html lets you override the header and branding, while templates/admin/blog/post/change_form.html overrides the change form only for the Post model. The get_queryset() method on ModelAdmin can be overridden to restrict the objects a staff user can see — for example showing only the posts they authored rather than all posts. The save_model() method is overridden to inject data before saving, such as setting the last_modified_by field. The has_add_permission(), has_change_permission(), and has_delete_permission() methods allow fine-grained per-object access control in the admin.
Example
# blog/admin.py — site customisation and per-user queryset filtering
from django.contrib import admin
from .models import Post

# --- Branding ---
admin.site.site_header = 'My Blog Administration'
admin.site.site_title  = 'My Blog Admin'
admin.site.index_title = 'Dashboard'


@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_display = ['title', 'author', 'status', 'published_at']

    def get_queryset(self, request):
        """Non-superusers only see their own posts."""
        qs = super().get_queryset(request)
        if request.user.is_superuser:
            return qs
        return qs.filter(author=request.user)

    def save_model(self, request, obj, form, change):
        """Auto-assign author on create."""
        if not change:
            obj.author = request.user
        super().save_model(request, obj, form, change)

    def has_change_permission(self, request, obj=None):
        if obj is not None and not request.user.is_superuser:
            return obj.author == request.user
        return super().has_change_permission(request, obj)

    def has_delete_permission(self, request, obj=None):
        if obj is not None and not request.user.is_superuser:
            return obj.author == request.user
        return super().has_delete_permission(request, obj)


# templates/admin/base_site.html — override header
# {% extends "admin/base.html" %}
# {% block branding %}
# <h1 id="site-name"><a href="{% url 'admin:index' %}">My Blog Admin</a></h1>
# {% endblock %}