Skip to main content
Advertisement

Django Admin Customization

Django Admin is an auto-generated admin interface based on your models. CRUD is available immediately with no extra code.


Basic Admin Registration

from django.contrib import admin
from .models import Category, Product, Review

admin.site.register(Category)

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
pass

list_display — List Columns

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ["id", "name", "price", "stock", "category", "is_active", "created_at"]
list_display_links = ["id", "name"]
list_editable = ["is_active", "stock"]
list_filter = ["is_active", "category", "created_at"]
search_fields = ["name", "description", "owner__email"]
ordering = ["-created_at"]
list_per_page = 25

def price_display(self, obj):
return f"${obj.price:,.2f}"
price_display.short_description = "Price"
price_display.admin_order_field = "price"

Detail Form Customization

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
fieldsets = [
("Basic Info", {
"fields": ["name", "description", "category"],
}),
("Price & Stock", {
"fields": ["price", "stock"],
"classes": ["wide"],
}),
("Settings", {
"fields": ["is_active", "owner"],
"classes": ["collapse"],
}),
]

readonly_fields = ["created_at", "updated_at"]
autocomplete_fields = ["category", "owner"]
raw_id_fields = ["owner"]

Custom Actions

from django.contrib import admin, messages


@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ["name", "is_active", "stock"]
actions = ["activate_products", "deactivate_products", "restock"]

@admin.action(description="Activate selected products")
def activate_products(self, request, queryset):
count = queryset.update(is_active=True)
self.message_user(request, f"{count} products activated")

@admin.action(description="Deactivate selected products")
def deactivate_products(self, request, queryset):
count = queryset.update(is_active=False)
self.message_user(request, f"{count} products deactivated", messages.WARNING)

@admin.action(description="Reset stock to 100")
def restock(self, request, queryset):
count = queryset.update(stock=100)
self.message_user(request, f"{count} products restocked to 100")

from django.contrib import admin
from .models import Product, Review


class ReviewInline(admin.TabularInline):
model = Review
fields = ["author", "rating", "comment"]
readonly_fields = ["created_at"]
extra = 0
max_num = 10


@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ["name", "price", "review_count"]
inlines = [ReviewInline]

def review_count(self, obj):
return obj.reviews.count()
review_count.short_description = "Reviews"

def get_queryset(self, request):
return super().get_queryset(request).prefetch_related("reviews")

Permission Control

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
def has_add_permission(self, request):
return request.user.is_superuser

def has_change_permission(self, request, obj=None):
if obj and obj.owner == request.user:
return True
return request.user.is_staff

def has_delete_permission(self, request, obj=None):
return request.user.is_superuser

def get_queryset(self, request):
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(owner=request.user)

Admin Site Customization

admin.site.site_header = "My Shop Admin"
admin.site.site_title = "My Shop Admin"
admin.site.index_title = "Dashboard"

Summary

FeatureAttribute/Method
List columnslist_display
Inline editlist_editable
Sidebar filterlist_filter
Searchsearch_fields
Form groupsfieldsets
Read-onlyreadonly_fields
Custom actionsactions + @admin.action
Related inlineTabularInline / StackedInline
Permission controlhas_*_permission()

Django Admin is best suited for internal tools and content management systems.

Advertisement