Admin Interface
The Django-CFG sample project showcases a modern, customizable admin interface built on the Unfold theme. This guide covers admin customization, dashboard widgets, and navigation configuration.
Unfold Theme Integration
The sample project uses the Unfold theme for a modern, Material Design-inspired admin interface.
Theme Configuration
Configure the theme in api/config.py:
from django_cfg import UnfoldConfig
unfold: UnfoldConfig = UnfoldConfig(
site_title="Django-CFG Sample Admin",
site_header="Django-CFG Sample",
site_url="/",
site_icon={
"light": "/static/icon-light.svg",
"dark": "/static/icon-dark.svg",
},
navigation=[...], # Navigation structure
colors={
"primary": {
"50": "250 245 255",
"100": "243 232 255",
"200": "233 213 255",
"300": "196 181 253",
"400": "147 51 234",
"500": "124 58 237",
"600": "109 40 217",
}
}
)Theme Options
Basic Settings
UnfoldConfig(
site_title="My Admin", # Browser tab title
site_header="My Site Admin", # Admin header text
site_url="/", # Logo link URL
index_title="Dashboard", # Index page title
)Branding
UnfoldConfig(
site_icon={
"light": "/static/icon-light.svg", # Light mode icon
"dark": "/static/icon-dark.svg", # Dark mode icon
},
site_logo={
"light": "/static/logo-light.svg", # Light mode logo
"dark": "/static/logo-dark.svg", # Dark mode logo
},
)Colors
Customize the color scheme:
UnfoldConfig(
colors={
"primary": {
"50": "250 245 255", # Lightest
"100": "243 232 255",
"200": "233 213 255",
"300": "196 181 253",
"400": "147 51 234",
"500": "124 58 237", # Base color
"600": "109 40 217", # Darkest
}
}
)Navigation Structure
Custom Navigation
Define a custom navigation menu:
unfold: UnfoldConfig = UnfoldConfig(
navigation=[
{
"title": "Dashboard",
"separator": True,
"items": [
{
"title": "Overview",
"icon": "dashboard",
"link": "/admin/",
},
]
},
{
"title": "Content Management",
"separator": True,
"items": [
{
"title": "Blog Posts",
"icon": "article",
"link": "/admin/blog/post/",
},
{
"title": "Comments",
"icon": "comment",
"link": "/admin/blog/comment/",
},
]
},
{
"title": "E-Commerce",
"separator": True,
"items": [
{
"title": "Products",
"icon": "inventory",
"link": "/admin/shop/product/",
},
{
"title": "Orders",
"icon": "shopping_cart",
"link": "/admin/shop/order/",
},
]
},
{
"title": "User Management",
"separator": True,
"items": [
{
"title": "Users",
"icon": "people",
"link": "/admin/auth/user/",
},
{
"title": "Profiles",
"icon": "account_circle",
"link": "/admin/profiles/profile/",
},
]
}
]
)Navigation Options
Separators
Add visual separators between sections:
{
"title": "Section Name",
"separator": True, # Adds separator above section
"items": [...]
}Icons
Use Material Design icons:
{
"title": "Dashboard",
"icon": "dashboard", # Material icon name
"link": "/admin/",
}Common icons:
dashboard- Dashboard/overviewarticle- Blog posts/contentinventory- Products/itemsshopping_cart- Orders/cartpeople- Userssettings- Settingsanalytics- Analytics/reports
Collapsible Sections
Create expandable sections:
{
"title": "Reports",
"collapsible": True,
"items": [
{"title": "Sales Report", "link": "/admin/reports/sales/"},
{"title": "User Report", "link": "/admin/reports/users/"},
]
}Model Admin Customization
Basic Admin Registration
# apps/blog/admin.py
from django.contrib import admin
from unfold.admin import ModelAdmin
from .models import Post, Comment
@admin.register(Post)
class PostAdmin(ModelAdmin):
list_display = ['title', 'author', 'status', 'created_at']
list_filter = ['status', 'created_at']
search_fields = ['title', 'content']
date_hierarchy = 'created_at'
fieldsets = (
('Content', {
'fields': ('title', 'content', 'status')
}),
('Metadata', {
'fields': ('author', 'created_at', 'updated_at'),
'classes': ('collapse',)
}),
)
readonly_fields = ['created_at', 'updated_at']List Display Customization
@admin.register(Order)
class OrderAdmin(ModelAdmin):
list_display = [
'id',
'user_email',
'total_amount',
'status_badge',
'created_at'
]
def user_email(self, obj):
return obj.user.email
user_email.short_description = 'Customer'
def total_amount(self, obj):
return f"${obj.total:,.2f}"
total_amount.short_description = 'Total'
def status_badge(self, obj):
colors = {
'pending': 'warning',
'processing': 'info',
'completed': 'success',
'cancelled': 'danger'
}
return f'<span class="badge badge-{colors[obj.status]}">{obj.status}</span>'
status_badge.short_description = 'Status'
status_badge.allow_tags = TrueInline Editing
class OrderItemInline(admin.TabularInline):
model = OrderItem
extra = 1
fields = ['product', 'quantity', 'price']
@admin.register(Order)
class OrderAdmin(ModelAdmin):
inlines = [OrderItemInline]Actions
Add custom bulk actions:
@admin.register(Post)
class PostAdmin(ModelAdmin):
actions = ['publish_posts', 'unpublish_posts']
def publish_posts(self, request, queryset):
updated = queryset.update(status='published')
self.message_user(
request,
f'{updated} post(s) published successfully.'
)
publish_posts.short_description = 'Publish selected posts'
def unpublish_posts(self, request, queryset):
updated = queryset.update(status='draft')
self.message_user(
request,
f'{updated} post(s) unpublished.'
)
unpublish_posts.short_description = 'Unpublish selected posts'Advanced Features
Tabbed Interface
Organize fields in tabs:
@admin.register(Product)
class ProductAdmin(ModelAdmin):
fieldsets = (
('Basic Information', {
'fields': ('name', 'description', 'category')
}),
('Pricing', {
'fields': ('price', 'discount_price', 'tax_rate')
}),
('Inventory', {
'fields': ('stock', 'reorder_level', 'supplier')
}),
('Media', {
'fields': ('image', 'gallery')
}),
)Filters
Add sidebar filters:
@admin.register(Post)
class PostAdmin(ModelAdmin):
list_filter = [
'status',
'created_at',
('author', admin.RelatedFieldListFilter),
]Search
Configure search functionality:
@admin.register(Product)
class ProductAdmin(ModelAdmin):
search_fields = [
'name',
'description',
'sku',
'category__name'
]Autocomplete
Enable autocomplete for foreign keys:
@admin.register(Post)
class PostAdmin(ModelAdmin):
autocomplete_fields = ['author', 'category']
@admin.register(User)
class UserAdmin(ModelAdmin):
search_fields = ['email', 'first_name', 'last_name']Sidebar Configuration
Sidebar Settings
UnfoldConfig(
sidebar={
"show_search": True, # Enable search box
"show_all_applications": False, # Hide ungrouped apps
"navigation": [...], # Custom navigation
}
)Search Box
Enable global search in sidebar:
sidebar={
"show_search": True,
}Users can search for:
- Model names
- Navigation items
- Recent actions
Accessing the Admin
Login
Visit http://127.0.0.1:8000/admin/ and login with:
- Email:
[email protected] - Password:
admin123
Creating Superuser
Create additional admin users:
# Interactive prompt
python manage.py createsuperuser
# With credentials
python manage.py createsuperuser \
--email [email protected] \
--noinputPermissions
Control admin access:
@admin.register(Post)
class PostAdmin(ModelAdmin):
def has_delete_permission(self, request, obj=None):
# Only superusers can delete
return request.user.is_superuser
def get_queryset(self, request):
# Users only see their own posts
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(author=request.user)Best Practices
1. Organize Navigation Logically
Group related items together:
# ✅ Good: Logical grouping
navigation=[
{"title": "Content", "items": [...]},
{"title": "E-Commerce", "items": [...]},
{"title": "Users", "items": [...]},
]
# ❌ Bad: Random order
navigation=[
{"title": "Orders", ...},
{"title": "Posts", ...},
{"title": "Products", ...},
]2. Use Meaningful Dashboard Metrics
Show actionable business metrics:
# ✅ Good: Actionable metrics
{
"title": "Orders Today",
"value": "23",
"description": "+12% vs yesterday"
}
# ❌ Bad: Meaningless numbers
{
"title": "Database Records",
"value": "1,234,567"
}3. Customize List Displays
Make lists informative and scannable:
# ✅ Good: Relevant information
list_display = ['title', 'author', 'status', 'views', 'created_at']
# ❌ Bad: Too much or too little
list_display = ['id']4. Add Helpful Actions
Provide bulk operations:
# ✅ Good: Common operations
actions = ['publish_posts', 'archive_posts', 'export_csv']
# ❌ Bad: Only default delete actionRelated Topics
- Configuration - Unfold configuration details
- Authentication - User authentication setup
- Project Structure - Admin file organization
A well-designed admin interface improves productivity and user experience!