Skip to main content

Django Admin Introduction

Django's administration interface is one of the framework's most powerful features that sets it apart from other web frameworks. The Django admin site provides a ready-to-use interface for managing your application's content, allowing you to perform CRUD (Create, Read, Update, Delete) operations on your data without writing any additional code.

What is Django Admin?

The Django admin is an automatic, model-centric interface where trusted users can manage your site's content. It reads metadata from your models to provide a quick, model-centric interface where authorized users can manage content on your site.

It's designed to be:

  • Secure: Built with authorization and authentication systems
  • Fast to set up: Often requiring just a few lines of code
  • Customizable: Can be extended to suit your specific needs

Why Use Django Admin?

  1. Rapid development: Get a fully-functional admin interface with minimal code
  2. Database management: Easily manage your application's data through a web interface
  3. Content management: Allow non-technical team members to manage site content
  4. Prototyping: Quickly build and test models with immediate visual feedback
  5. Site maintenance: Perform administrative tasks without direct database access

Getting Started with Django Admin

Let's start with a simple example to understand how Django admin works. We'll create a simple blog application and configure the admin interface.

Step 1: Create a Django Project and App

If you haven't already, create a new Django project and app:

bash
# Create a new Django project
django-admin startproject myproject

# Navigate to the project directory
cd myproject

# Create a new app called 'blog'
python manage.py startapp blog

Step 2: Add the App to Your Project

In myproject/settings.py, add your app to the INSTALLED_APPS list:

python
INSTALLED_APPS = [
'django.contrib.admin', # Django admin is already included by default
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog', # Add your blog app here
]

Step 3: Define Models

In blog/models.py, define a simple blog post model:

python
from django.db import models
from django.contrib.auth.models import User

class Category(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(blank=True)

def __str__(self):
return self.name

class Meta:
verbose_name_plural = "Categories"

class BlogPost(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True)
published_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(auto_now=True)
is_published = models.BooleanField(default=False)

def __str__(self):
return self.title

Step 4: Register Models with the Admin Interface

Create or modify blog/admin.py to register your models:

python
from django.contrib import admin
from .models import Category, BlogPost

# Basic registration
admin.site.register(Category)
admin.site.register(BlogPost)

Step 5: Create Database Tables and a Superuser

Run migrations to create your database tables:

bash
python manage.py makemigrations
python manage.py migrate

Create a superuser to access the admin interface:

bash
python manage.py createsuperuser

Follow the prompts to create a username, email address, and password.

Step 6: Run the Development Server

Start the development server:

bash
python manage.py runserver

Now, visit http://localhost:8000/admin/ in your browser and log in with your superuser credentials.

Exploring the Admin Interface

After logging in, you'll see the Django admin dashboard with your registered models. Here's what you can do:

  1. Browse models: See all your registered models in the index page
  2. View records: Click on a model to see all its records in a list
  3. Add new records: Click "Add" to create new instances of a model
  4. Edit records: Click on any record to modify its fields
  5. Delete records: Select records and use the dropdown to delete them
  6. Filter and search: Use the filter sidebar and search box to find specific records

Enhancing the Admin Interface

The default admin interface is useful, but you can make it even better with some customizations:

Customizing the List Display

Let's improve how the blog posts are displayed in the admin:

python
from django.contrib import admin
from .models import Category, BlogPost

# Register Category model
admin.site.register(Category)

# Custom admin configuration for BlogPost
@admin.register(BlogPost)
class BlogPostAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'category', 'published_date', 'is_published')
list_filter = ('is_published', 'category', 'author')
search_fields = ('title', 'content')
date_hierarchy = 'published_date'
ordering = ('-published_date',)

Now the admin list view for BlogPost will show multiple columns, have filters, search capabilities, and date-based navigation.

Adding List Actions

You can add custom actions to the admin interface:

python
@admin.register(BlogPost)
class BlogPostAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'category', 'published_date', 'is_published')
list_filter = ('is_published', 'category', 'author')
search_fields = ('title', 'content')
date_hierarchy = 'published_date'
ordering = ('-published_date',)

actions = ['make_published', 'make_unpublished']

def make_published(self, request, queryset):
queryset.update(is_published=True)
make_published.short_description = "Mark selected posts as published"

def make_unpublished(self, request, queryset):
queryset.update(is_published=False)
make_unpublished.short_description = "Mark selected posts as unpublished"

Customizing Form Layout

You can control how the edit form is displayed:

python
@admin.register(BlogPost)
class BlogPostAdmin(admin.ModelAdmin):
fieldsets = (
('Post Information', {
'fields': ('title', 'content', 'category')
}),
('Publication Information', {
'fields': ('author', 'is_published'),
'classes': ('collapse',)
}),
)

Real-World Example: Managing a Blog Platform

Let's expand our blog application to include comments and tags, showing how Django admin can manage more complex relationships.

Extended Models

python
# blog/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)

def __str__(self):
return self.name

class Meta:
verbose_name_plural = "Categories"

class Tag(models.Model):
name = models.CharField(max_length=50)
slug = models.SlugField(unique=True)

def __str__(self):
return self.name

class BlogPost(models.Model):
title = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
content = models.TextField()
excerpt = models.TextField(blank=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True)
tags = models.ManyToManyField(Tag, blank=True)
featured_image = models.ImageField(upload_to='blog/images/', blank=True, null=True)
published_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(auto_now=True)
is_published = models.BooleanField(default=False)
views = models.PositiveIntegerField(default=0)

def __str__(self):
return self.title

class Comment(models.Model):
post = models.ForeignKey(BlogPost, on_delete=models.CASCADE, related_name='comments')
name = models.CharField(max_length=100)
email = models.EmailField()
body = models.TextField()
created_date = models.DateTimeField(auto_now_add=True)
approved = models.BooleanField(default=False)

def __str__(self):
return f"Comment by {self.name} on {self.post.title}"

Enhanced Admin Configuration

python
# blog/admin.py
from django.contrib import admin
from .models import Category, Tag, BlogPost, Comment

@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
list_display = ('name', 'slug')
prepopulated_fields = {'slug': ('name',)}

@admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
list_display = ('name', 'slug')
prepopulated_fields = {'slug': ('name',)}

class CommentInline(admin.TabularInline):
model = Comment
extra = 0

@admin.register(BlogPost)
class BlogPostAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'category', 'is_published', 'published_date', 'views')
list_filter = ('is_published', 'category', 'author', 'tags')
search_fields = ('title', 'content', 'excerpt')
prepopulated_fields = {'slug': ('title',)}
date_hierarchy = 'published_date'
filter_horizontal = ('tags',)
readonly_fields = ('views', 'published_date', 'updated_date')
inlines = [CommentInline]

fieldsets = (
('Content', {
'fields': ('title', 'slug', 'content', 'excerpt', 'featured_image')
}),
('Classification', {
'fields': ('category', 'tags')
}),
('Publication', {
'fields': ('author', 'is_published', 'published_date', 'updated_date')
}),
('Metrics', {
'fields': ('views',),
'classes': ('collapse',)
}),
)

actions = ['make_published', 'make_unpublished']

def make_published(self, request, queryset):
rows_updated = queryset.update(is_published=True)
self.message_user(request, f"{rows_updated} posts were successfully marked as published.")
make_published.short_description = "Mark selected posts as published"

def make_unpublished(self, request, queryset):
rows_updated = queryset.update(is_published=False)
self.message_user(request, f"{rows_updated} posts were successfully marked as unpublished.")
make_unpublished.short_description = "Mark selected posts as unpublished"

@admin.register(Comment)
class CommentAdmin(admin.ModelAdmin):
list_display = ('name', 'email', 'post', 'created_date', 'approved')
list_filter = ('approved', 'created_date')
search_fields = ('name', 'email', 'body')
actions = ['approve_comments', 'disapprove_comments']

def approve_comments(self, request, queryset):
queryset.update(approved=True)
approve_comments.short_description = "Approve selected comments"

def disapprove_comments(self, request, queryset):
queryset.update(approved=False)
disapprove_comments.short_description = "Disapprove selected comments"

This comprehensive configuration demonstrates how Django admin can handle complex data relationships, inline editing, custom actions, and more.

Summary

Django's admin interface is a powerful tool that:

  1. Provides immediate access to your application's data through a user-friendly interface
  2. Requires minimal setup for basic functionality
  3. Can be highly customized for specific needs
  4. Supports complex data relationships
  5. Offers features like filtering, searching, and custom actions

Whether you're building a simple application or a complex web platform, Django admin can significantly reduce the development time needed for management interfaces and provide immediate value to your project.

Additional Resources

Exercises

  1. Basic Admin Setup: Create a simple movie database with models for movies, directors, and genres. Register them with the Django admin.

  2. Custom List Display: Enhance your movie admin to show relevant information in the list view (release year, director, rating, etc.).

  3. Admin Actions: Add a custom action to mark movies as "featured" or "classic".

  4. Inline Editing: Set up the admin to allow adding cast members directly from the movie editing page.

  5. Advanced Customization: Create a custom admin site theme by overriding Django admin templates and adding your own CSS.

By mastering Django admin, you'll have a powerful tool to manage your application's data efficiently while focusing more time on building your application's core features.



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)