Admin Site

Enabling the Admin

Django's admin interface comes built-in but requires some initial setup. This chapter covers everything you need to know to get the admin interface up and running.

Enabling the Admin

Django's admin interface comes built-in but requires some initial setup. This chapter covers everything you need to know to get the admin interface up and running.

Initial Setup

1. Install Admin App

The admin app is included by default in INSTALLED_APPS:

# settings.py
INSTALLED_APPS = [
    'django.contrib.admin',        # Admin interface
    'django.contrib.auth',         # Authentication system
    'django.contrib.contenttypes', # Content types framework
    'django.contrib.sessions',     # Session framework
    'django.contrib.messages',     # Messaging framework
    'django.contrib.staticfiles',  # Static files handling
    # Your apps here
]

2. Configure URLs

Add admin URLs to your project's URL configuration:

# urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    # Your other URL patterns
]

3. Run Migrations

Create the necessary database tables:

python manage.py migrate

4. Create Superuser

Create an admin user account:

python manage.py createsuperuser

You'll be prompted to enter:

  • Username
  • Email address (optional)
  • Password

Admin Configuration

Basic Settings

# settings.py

# Admin site configuration
ADMIN_URL = 'admin/'  # Change this for security

# Admin site headers and titles
ADMIN_SITE_HEADER = 'My Site Administration'
ADMIN_SITE_TITLE = 'My Site Admin'
ADMIN_INDEX_TITLE = 'Welcome to My Site Administration'

# Date and time formatting
USE_L10N = True
USE_TZ = True
TIME_ZONE = 'UTC'

# Language settings
LANGUAGE_CODE = 'en-us'
USE_I18N = True

Custom Admin Site

Create a custom admin site for more control:

# admin.py
from django.contrib import admin
from django.contrib.admin import AdminSite
from django.urls import path

class MyAdminSite(AdminSite):
    """Custom admin site"""
    
    site_header = 'My Custom Administration'
    site_title = 'My Admin'
    index_title = 'Welcome to My Administration'
    
    def get_urls(self):
        """Add custom URLs to admin"""
        urls = super().get_urls()
        custom_urls = [
            path('custom-view/', self.admin_view(self.custom_view), name='custom_view'),
        ]
        return custom_urls + urls
    
    def custom_view(self, request):
        """Custom admin view"""
        from django.shortcuts import render
        context = {
            'title': 'Custom Admin View',
            'site_header': self.site_header,
        }
        return render(request, 'admin/custom_view.html', context)

# Create custom admin site instance
admin_site = MyAdminSite(name='myadmin')

# Use in URLs
# urls.py
from myapp.admin import admin_site

urlpatterns = [
    path('admin/', admin_site.urls),
]

Admin Interface Customization

Changing Admin Templates

Override admin templates by creating them in your templates directory:

<!-- templates/admin/base_site.html -->
{% extends "admin/base.html" %}

{% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %}

{% block branding %}
<h1 id="site-name">
    <a href="{% url 'admin:index' %}">
        <img src="{% load static %}{% static 'admin/img/logo.png' %}" alt="Logo" height="40">
        My Site Administration
    </a>
</h1>
{% endblock %}

{% block nav-global %}{% endblock %}

Custom CSS and JavaScript

Add custom styling to the admin:

# admin.py
class MyModelAdmin(admin.ModelAdmin):
    class Media:
        css = {
            'all': ('admin/css/custom.css',)
        }
        js = ('admin/js/custom.js',)
/* static/admin/css/custom.css */
#header {
    background: #2c3e50;
}

#branding h1 {
    color: #ecf0f1;
}

.module h2, .module caption, .inline-group h2 {
    background: #34495e;
}

Admin Security Configuration

Secure Admin URL

Change the admin URL for security:

# urls.py
from django.contrib import admin
from django.urls import path
import os

# Use environment variable for admin URL
admin_url = os.environ.get('ADMIN_URL', 'admin/')

urlpatterns = [
    path(admin_url, admin.site.urls),
]

IP Restriction Middleware

Restrict admin access by IP address:

# middleware.py
from django.http import HttpResponseForbidden
from django.conf import settings
import ipaddress

class AdminIPRestrictionMiddleware:
    """Restrict admin access to specific IP addresses"""
    
    def __init__(self, get_response):
        self.get_response = get_response
        self.allowed_ips = getattr(settings, 'ADMIN_ALLOWED_IPS', [])
    
    def __call__(self, request):
        if request.path.startswith('/admin/'):
            client_ip = self.get_client_ip(request)
            
            if not self.is_ip_allowed(client_ip):
                return HttpResponseForbidden('Access denied')
        
        return self.get_response(request)
    
    def get_client_ip(self, request):
        """Get client IP address"""
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]
        else:
            ip = request.META.get('REMOTE_ADDR')
        return ip
    
    def is_ip_allowed(self, ip):
        """Check if IP is in allowed list"""
        if not self.allowed_ips:
            return True  # No restrictions if list is empty
        
        try:
            client_ip = ipaddress.ip_address(ip)
            for allowed_ip in self.allowed_ips:
                if client_ip in ipaddress.ip_network(allowed_ip, strict=False):
                    return True
        except ValueError:
            pass
        
        return False

# settings.py
MIDDLEWARE = [
    # ... other middleware
    'myapp.middleware.AdminIPRestrictionMiddleware',
]

# Allowed IP addresses/networks
ADMIN_ALLOWED_IPS = [
    '192.168.1.0/24',  # Local network
    '10.0.0.1',        # Specific IP
]

Environment-Specific Configuration

Development Settings

# settings/development.py
from .base import *

# Admin configuration for development
ADMIN_URL = 'admin/'
DEBUG = True

# Allow all IPs in development
ADMIN_ALLOWED_IPS = []

# Admin site customization
ADMIN_SITE_HEADER = 'My Site Admin (Development)'

Production Settings

# settings/production.py
from .base import *
import os

# Secure admin configuration
ADMIN_URL = os.environ.get('ADMIN_URL', 'secure-admin-panel/')
DEBUG = False

# Restrict admin access
ADMIN_ALLOWED_IPS = [
    '203.0.113.0/24',  # Office network
]

# Production admin customization
ADMIN_SITE_HEADER = 'My Site Administration'

# Additional security
SECURE_SSL_REDIRECT = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

Admin Logging and Monitoring

Admin Action Logging

Django automatically logs admin actions, but you can customize this:

# models.py
from django.contrib.admin.models import LogEntry, ADDITION, CHANGE, DELETION
from django.contrib.contenttypes.models import ContentType

def log_admin_action(user, obj, action_flag, change_message=''):
    """Log custom admin action"""
    LogEntry.objects.log_action(
        user_id=user.id,
        content_type_id=ContentType.objects.get_for_model(obj).pk,
        object_id=obj.pk,
        object_repr=str(obj),
        action_flag=action_flag,
        change_message=change_message
    )

# Usage in views or admin methods
log_admin_action(
    user=request.user,
    obj=my_object,
    action_flag=CHANGE,
    change_message='Custom action performed'
)

Admin Activity Monitoring

# admin.py
from django.contrib.admin.models import LogEntry
from django.contrib import admin

@admin.register(LogEntry)
class LogEntryAdmin(admin.ModelAdmin):
    """Admin interface for viewing admin logs"""
    
    list_display = [
        'action_time',
        'user',
        'content_type',
        'object_repr',
        'action_flag',
        'change_message'
    ]
    
    list_filter = [
        'action_time',
        'user',
        'content_type',
        'action_flag'
    ]
    
    search_fields = [
        'object_repr',
        'change_message'
    ]
    
    readonly_fields = [
        'action_time',
        'user',
        'content_type',
        'object_id',
        'object_repr',
        'action_flag',
        'change_message'
    ]
    
    def has_add_permission(self, request):
        return False
    
    def has_change_permission(self, request, obj=None):
        return False
    
    def has_delete_permission(self, request, obj=None):
        return False

Admin Performance Optimization

Database Query Optimization

# admin.py
class OptimizedModelAdmin(admin.ModelAdmin):
    """Optimized admin with efficient queries"""
    
    def get_queryset(self, request):
        """Optimize queryset with select_related and prefetch_related"""
        queryset = super().get_queryset(request)
        return queryset.select_related(
            'user',
            'category'
        ).prefetch_related(
            'tags',
            'comments'
        )
    
    def get_list_display(self, request):
        """Dynamic list display based on user permissions"""
        list_display = ['title', 'user', 'created_at']
        
        if request.user.has_perm('myapp.view_advanced_fields'):
            list_display.extend(['status', 'priority'])
        
        return list_display

Caching Admin Views

# admin.py
from django.views.decorators.cache import cache_page
from django.utils.decorators import method_decorator

@method_decorator(cache_page(60 * 15), name='changelist_view')  # 15 minutes
class CachedModelAdmin(admin.ModelAdmin):
    """Admin with cached changelist view"""
    
    def changelist_view(self, request, extra_context=None):
        """Cached changelist view"""
        return super().changelist_view(request, extra_context)

Testing Admin Configuration

Admin Tests

# tests.py
from django.test import TestCase, Client
from django.contrib.auth.models import User
from django.urls import reverse

class AdminTestCase(TestCase):
    """Test admin interface"""
    
    def setUp(self):
        self.client = Client()
        self.superuser = User.objects.create_superuser(
            username='admin',
            email='admin@example.com',
            password='testpass123'
        )
    
    def test_admin_login(self):
        """Test admin login"""
        response = self.client.post(reverse('admin:login'), {
            'username': 'admin',
            'password': 'testpass123'
        })
        self.assertEqual(response.status_code, 302)
    
    def test_admin_access(self):
        """Test admin access after login"""
        self.client.login(username='admin', password='testpass123')
        response = self.client.get(reverse('admin:index'))
        self.assertEqual(response.status_code, 200)
    
    def test_model_admin_access(self):
        """Test model admin access"""
        self.client.login(username='admin', password='testpass123')
        response = self.client.get(reverse('admin:myapp_mymodel_changelist'))
        self.assertEqual(response.status_code, 200)

Troubleshooting Common Issues

Static Files Not Loading

# settings.py
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

# For development
if DEBUG:
    from django.conf.urls.static import static
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

Admin CSS/JS Issues

# Collect static files
python manage.py collectstatic

# Clear browser cache
# Check STATIC_URL and STATIC_ROOT settings
# Verify static files middleware is installed

Permission Errors

# Check user permissions
user.is_staff = True      # Required for admin access
user.is_superuser = True  # Full admin access
user.save()

# Or assign specific permissions
from django.contrib.auth.models import Permission
permission = Permission.objects.get(codename='add_mymodel')
user.user_permissions.add(permission)

Next Steps

Now that you have the admin interface enabled and configured, let's learn how to register your models and make them available in the admin interface.