Chapter 10: Django Admin Interface
10.1 Admin Basics
Create Superuser
Django admin is a powerful CRUD interface that lets admin users manage website content. First, create a superuser to access the admin:
bash
# Create superuser
python manage.py createsuperuser
# Enter username, email, and password when prompted
Username (leave blank to use 'yourname'): admin
Email address: admin@example.com
Password: ********
Password (again): ********
Superuser created successfully.Create superuser programmatically:
python
# In Django shell
from django.contrib.auth.models import User
# Method 1: Use create_superuser
user = User.objects.create_superuser(
username='admin',
email='admin@example.com',
password='securepassword'
)
# Method 2: Create user then set superuser permissions
user = User.objects.create_user(
username='admin',
email='admin@example.com',
password='securepassword'
)
user.is_staff = True
user.is_superuser = True
user.save()Auto-create superuser during deployment:
python
# management/commands/create_admin.py
from django.core.management.base import BaseCommand
from django.contrib.auth.models import User
import os
class Command(BaseCommand):
help = 'Create a superuser if it does not exist'
def handle(self, *args, **options):
username = os.environ.get('DJANGO_SUPERUSER_USERNAME', 'admin')
email = os.environ.get('DJANGO_SUPERUSER_EMAIL', 'admin@example.com')
password = os.environ.get('DJANGO_SUPERUSER_PASSWORD', 'admin')
if not User.objects.filter(username=username).exists():
User.objects.create_superuser(username, email, password)
self.stdout.write(
self.style.SUCCESS(f'Superuser {username} created successfully')
)
else:
self.stdout.write(
self.style.WARNING(f'Superuser {username} already exists')
)Register Models
To make models visible in admin, register them in the app's admin.py:
python
# models.py
from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(unique=True)
description = models.TextField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = "Category"
verbose_name_plural = "Categories"
def __str__(self):
return self.name
class Tag(models.Model):
name = models.CharField(max_length=50)
slug = models.SlugField(unique=True)
class Meta:
verbose_name = "Tag"
verbose_name_plural = "Tags"
def __str__(self):
return self.name
class Article(models.Model):
title = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
tags = models.ManyToManyField(Tag, blank=True)
content = models.TextField()
excerpt = models.TextField(blank=True)
is_published = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = "Article"
verbose_name_plural = "Articles"
ordering = ['-created_at']
def __str__(self):
return self.title
# admin.py
from django.contrib import admin
from .models import Category, Tag, Article
# Basic registration
admin.site.register(Category)
admin.site.register(Tag)
# Register with decorator
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
list_display = ['title', 'author', 'category', 'is_published', 'created_at']
list_filter = ['is_published', 'category', 'created_at']
search_fields = ['title', 'content']
prepopulated_fields = {'slug': ('title',)}
date_hierarchy = 'created_at'Admin Interface Customization
Customize admin interface for better usability:
python
# admin.py
from django.contrib import admin
from django.utils.html import format_html
from .models import Category, Tag, Article
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
list_display = ['name', 'slug', 'article_count', 'created_at']
list_filter = ['created_at']
search_fields = ['name', 'description']
prepopulated_fields = {'slug': ('name',)}
ordering = ['name']
def article_count(self, obj):
return obj.article_set.count()
article_count.short_description = 'Article Count'
@admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
list_display = ['name', 'slug', 'article_count']
search_fields = ['name']
prepopulated_fields = {'slug': ('name',)}
def article_count(self, obj):
return obj.article_set.count()
article_count.short_description = 'Article Count'
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
# List display
list_display = [
'title', 'author', 'category', 'is_published',
'created_at', 'preview_link'
]
list_filter = ['is_published', 'category', 'tags', 'created_at', 'author']
search_fields = ['title', 'content', 'excerpt']
ordering = ['-created_at']
date_hierarchy = 'created_at'
# Edit page
fieldsets = (
('Basic Info', {
'fields': ('title', 'slug', 'author', 'excerpt')
}),
('Content', {
'fields': ('content',),
'classes': ('wide',)
}),
('Category and Tags', {
'fields': ('category', 'tags')
}),
('Publish Settings', {
'fields': ('is_published',),
'classes': ('collapse',)
}),
)
# Prepopulated fields
prepopulated_fields = {'slug': ('title',)}
# Read-only fields
readonly_fields = ['created_at', 'updated_at']
# Foreign key search in filters
autocomplete_fields = ['author', 'category']
def preview_link(self, obj):
if obj.is_published:
return format_html(
'<a href="{}" target="_blank">Preview</a>',
obj.get_absolute_url()
)
return "Not Published"
preview_link.short_description = "Preview"
# Custom queryset
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
# Regular users can only see their own articles
return qs.filter(author=request.user)
# Custom save logic
def save_model(self, request, obj, form, change):
if not change: # Set author when creating new
obj.author = request.user
super().save_model(request, obj, form, change)Field Display Configuration
Configure how fields appear in admin:
python
# admin.py
from django.contrib import admin
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from .models import Article
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
list_display = [
'title', 'author', 'category', 'is_published',
'created_at', 'word_count', 'status_badge'
]
# Custom field display
def word_count(self, obj):
return len(obj.content.split())
word_count.short_description = 'Word Count'
word_count.admin_order_field = 'content' # Sortable
# Show status badge
def status_badge(self, obj):
if obj.is_published:
return format_html(
'<span style="background-color: #28a745; color: white; padding: 4px 8px; border-radius: 4px;">Published</span>'
)
else:
return format_html(
'<span style="background-color: #ffc107; color: black; padding: 4px 8px; border-radius: 4px;">Draft</span>'
)
status_badge.short_description = 'Status'
# Show rich text content preview
def content_preview(self, obj):
# Get first 200 characters
preview = obj.content[:200]
if len(obj.content) > 200:
preview += '...'
return mark_safe(preview)
content_preview.short_description = 'Content Preview'
# Conditional field display
def get_list_display(self, request):
# Superusers see all fields
if request.user.is_superuser:
return self.list_display + ['content_preview']
# Regular users don't see some fields
return [field for field in self.list_display if field != 'author']With these configurations, you can create a powerful and user-friendly Django admin interface.
Summary
Django admin basic features include:
- ✅ Create superuser via command line or programmatically
- ✅ Register models in admin.py to make them visible
- ✅ Customize admin interface for better user experience
- ✅ Configure field display and list filters
- ✅ Use decorators and ModelAdmin class for advanced customization
Mastering admin basics helps you quickly build content management systems.
Next
We will learn advanced admin configuration techniques.
10.2 Advanced Admin Configuration →