Django Admin interface
Master Django's built-in admin interface for managing your application's data and users.
60 min•By Priygop Team•Last updated: Feb 2026
Django Admin Overview
Django's admin interface is a powerful, automatically generated web interface for managing your application's data. It's highly customizable and provides a user-friendly way to interact with your models.
Admin Configuration
Example
# admin.py
from django.contrib import admin
from django.utils.html import format_html
from .models import Post, Category, Tag, Comment
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ['title', 'author', 'category', 'status', 'created_date', 'published_date']
list_filter = ['status', 'created_date', 'category', 'author']
search_fields = ['title', 'content']
prepopulated_fields = {'slug': ('title',)}
date_hierarchy = 'created_date'
ordering = ['-created_date']
fieldsets = (
('Content', {
'fields': ('title', 'slug', 'content', 'excerpt')
}),
('Metadata', {
'fields': ('author', 'category', 'tags', 'status')
}),
('Publishing', {
'fields': ('published_date',),
'classes': ('collapse',)
}),
)
def get_queryset(self, request):
return super().get_queryset(request).select_related('author', 'category')
def save_model(self, request, obj, form, change):
if not change: # New object
obj.author = request.user
super().save_model(request, obj, form, change)
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
list_display = ['name', 'slug', 'post_count']
prepopulated_fields = {'slug': ('name',)}
def post_count(self, obj):
return obj.post_set.count()
post_count.short_description = 'Number of Posts'
@admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
list_display = ['name', 'color_display', 'post_count']
search_fields = ['name']
def color_display(self, obj):
if obj.color:
return format_html(
'<span style="color: {};">{}</span>',
obj.color,
obj.color
)
return '-'
color_display.short_description = 'Color'
def post_count(self, obj):
return obj.post_set.count()
post_count.short_description = 'Number of Posts'
# Custom admin actions
@admin.action(description='Mark selected posts as published')
def make_published(modeladmin, request, queryset):
from django.utils import timezone
updated = queryset.update(status='published', published_date=timezone.now())
modeladmin.message_user(request, f'{updated} posts were successfully marked as published.')
@admin.action(description='Mark selected posts as draft')
def make_draft(modeladmin, request, queryset):
updated = queryset.update(status='draft', published_date=None)
modeladmin.message_user(request, f'{updated} posts were successfully marked as draft.')
# Add actions to PostAdmin
PostAdmin.actions = [make_published, make_draft]Practice Exercise: Custom Admin Dashboard
Example
# Custom Admin Dashboard
from django.contrib import admin
from django.contrib.admin import AdminSite
from django.utils.html import format_html
from django.urls import path
from django.shortcuts import render
from django.db.models import Count, Sum
from django.utils import timezone
from datetime import timedelta
class CustomAdminSite(AdminSite):
site_header = "My Django Site Administration"
site_title = "My Django Site Admin Portal"
index_title = "Welcome to My Django Site Administration"
def get_urls(self):
urls = super().get_urls()
custom_urls = [
path('dashboard/', self.admin_view(self.dashboard_view), name='dashboard'),
path('analytics/', self.admin_view(self.analytics_view), name='analytics'),
]
return custom_urls + urls
def dashboard_view(self, request):
"""Custom dashboard view"""
from .models import Post, User, Comment
# Get statistics
total_posts = Post.objects.count()
published_posts = Post.objects.filter(status='published').count()
total_users = User.objects.count()
total_comments = Comment.objects.count()
# Recent activity
recent_posts = Post.objects.order_by('-created_date')[:5]
recent_comments = Comment.objects.order_by('-created_date')[:5]
# Chart data
last_30_days = timezone.now() - timedelta(days=30)
daily_posts = Post.objects.filter(
created_date__gte=last_30_days
).extra(
select={'day': 'date(created_date)'}
).values('day').annotate(count=Count('id')).order_by('day')
context = {
'total_posts': total_posts,
'published_posts': published_posts,
'total_users': total_users,
'total_comments': total_comments,
'recent_posts': recent_posts,
'recent_comments': recent_comments,
'daily_posts': list(daily_posts),
}
return render(request, 'admin/dashboard.html', context)
def analytics_view(self, request):
"""Analytics view"""
from .models import Post, User
# User engagement metrics
user_engagement = User.objects.annotate(
post_count=Count('post'),
comment_count=Count('comment')
).order_by('-post_count')[:10]
# Category popularity
category_popularity = Post.objects.values('category__name').annotate(
post_count=Count('id')
).order_by('-post_count')
context = {
'user_engagement': user_engagement,
'category_popularity': category_popularity,
}
return render(request, 'admin/analytics.html', context)
# Register the custom admin site
admin_site = CustomAdminSite(name='custom_admin')
# Register models with custom admin site
admin_site.register(Post, PostAdmin)
admin_site.register(Category, CategoryAdmin)
admin_site.register(Tag, TagAdmin)
# Usage in urls.py:
# from .admin import admin_site
# urlpatterns = [
# path('admin/', admin_site.urls),
# ]