Dashboards¶
This guide explains how dashboards work in django-admin-deux and how they display your registered ModelAdmins.
Overview¶
django-admin-deux provides two types of dashboards:
- Project Dashboard - Shows all apps and their models
- App Dashboard - Shows all models within a specific app
Both dashboards serve as navigation hubs, displaying available ModelAdmins and their actions.
Project Dashboard¶
Accessing¶
Navigate to /djadmin/ (or your configured admin path) to see the project dashboard.
What It Shows¶
The project dashboard displays: - All Django apps that have registered ModelAdmins - All ModelAdmins within each app - General actions for each ModelAdmin (typically a ListView link)
Example Layout¶
┌─────────────────────────────────────────┐
│ Dashboard │
├─────────────────────────────────────────┤
│ │
│ Webshop │
│ ┌─────────────────────────────────────┐│
│ │ Categories [View List] [Add] ││
│ │ Products [View List] [Add] ││
│ │ Orders [View List] [Add] ││
│ └─────────────────────────────────────┘│
│ │
│ Blog │
│ ┌─────────────────────────────────────┐│
│ │ Posts [View List] [Add] ││
│ │ Comments [View List] [Add] ││
│ └─────────────────────────────────────┘│
└─────────────────────────────────────────┘
URL Patterns¶
# Project dashboard
reverse('djadmin:index') # /djadmin/
# With namespace
reverse('djadmin:index', current_app='djadmin')
Template¶
The project dashboard uses:
- djadmin/project_dashboard.html (from theme plugin)
- Context includes app_list with all apps and their ModelAdmins
App Dashboard¶
Accessing¶
Navigate to /djadmin/<app_label>/ to see a specific app's dashboard.
What It Shows¶
The app dashboard displays: - The app name - All ModelAdmins registered for that app - General actions for each ModelAdmin
Example Layout¶
┌─────────────────────────────────────────┐
│ Webshop │
├─────────────────────────────────────────┤
│ ┌─────────────────────────────────────┐│
│ │ Categories [View List] [Add] ││
│ │ Products [View List] [Add] ││
│ │ Customers [View List] [Add] ││
│ │ Orders [View List] [Add] ││
│ │ Reviews [View List] [Add] ││
│ │ Tags [View List] [Add] ││
│ └─────────────────────────────────────┘│
└─────────────────────────────────────────┘
URL Patterns¶
# App dashboard
reverse('djadmin:app_index', kwargs={'app_label': 'webshop'}) # /djadmin/webshop/
# With namespace
reverse('djadmin:app_index', kwargs={'app_label': 'webshop'}, current_app='djadmin')
Template¶
The app dashboard uses:
- djadmin/app_dashboard.html (from theme plugin)
- Context includes app_label, model_admins, and app_config
How ModelAdmins Are Displayed¶
Display Name¶
Each ModelAdmin is displayed with a name derived from the model:
# Model's verbose_name_plural is used
class Product(models.Model):
class Meta:
verbose_name_plural = "Products" # Shows as "Products" in dashboard
Multiple ModelAdmins for One Model¶
When you register multiple ModelAdmin classes for the same model, each appears as a separate entry:
@register(Product)
class SimpleProductAdmin(ModelAdmin):
list_display = ['name', 'price']
@register(Product)
class DetailedProductAdmin(ModelAdmin):
list_display = ['name', 'sku', 'price', 'stock_quantity', 'status']
# Dashboard shows:
# Product (SimpleProductAdmin) [View List] [Add]
# Product (DetailedProductAdmin) [View List] [Add]
Each gets its own URL:
- /djadmin/webshop/product/0/ → SimpleProductAdmin ListView
- /djadmin/webshop/product/1/ → DetailedProductAdmin ListView
Actions in Dashboards¶
General Actions¶
General actions are the primary actions displayed in dashboards. They represent main entry points to your ModelAdmin.
from djadmin.actions.list_view import ListAction
from djadmin.actions.dashboard import DashboardAction
@register(Product)
class ProductAdmin(ModelAdmin):
# Default: only ListAction
general_actions = [ListAction]
The default ListAction creates a "View List" link to the ListView.
List Actions in Dashboards¶
List actions may also appear in some dashboard layouts, typically as secondary buttons:
from djadmin.plugins.core.actions import AddAction
@register(Product)
class ProductAdmin(ModelAdmin):
# AddAction appears next to "View List" in dashboard
list_actions = [AddAction]
What Doesn't Appear¶
- Record actions - These appear in ListViews, not dashboards
- Bulk actions - These appear in ListViews when records are selected
Example Configuration¶
from djadmin import ModelAdmin, register
from djadmin.actions.list_view import ListAction
from djadmin.plugins.core.actions import AddAction
@register(Product)
class ProductAdmin(ModelAdmin):
# These appear in dashboard
general_actions = [ListAction]
list_actions = [AddAction]
# These don't appear in dashboard
record_actions = [EditAction, DeleteAction]
bulk_actions = [DeleteBulkAction]
Dashboard shows:
Customizing Dashboard Display¶
Hiding from Dashboard¶
Remove general actions to hide a ModelAdmin from dashboards:
@register(Product)
class HiddenProductAdmin(ModelAdmin):
general_actions = [] # Won't appear in dashboard
list_actions = [AddAction]
Note: The ModelAdmin still exists and is accessible via direct URL, but won't be listed in dashboards.
Custom Dashboard Actions¶
Create custom general actions for specialized entry points:
from djadmin.actions import BaseAction, GeneralActionMixin
class AnalyticsDashboardAction(GeneralActionMixin, BaseAction):
label = 'Analytics Dashboard'
icon = 'chart-bar'
css_class = 'secondary'
def get_url_pattern(self):
return f'{self.model._meta.app_label}/{self.model._meta.model_name}/analytics/'
def execute(self, request, **kwargs):
# Show analytics dashboard
context = {
'total_products': self.model.objects.count(),
'active_products': self.model.objects.filter(status='active').count(),
# ... more analytics
}
return render(request, 'myapp/analytics_dashboard.html', context)
@register(Product)
class ProductAdmin(ModelAdmin):
general_actions = [ListAction, AnalyticsDashboardAction]
Dashboard shows:
Read-Only Dashboard Entry¶
Create a dashboard entry without modification actions:
@register(Product)
class ReadOnlyProductAdmin(ModelAdmin):
general_actions = [ListAction] # Only view list
list_actions = [] # No add
record_actions = [] # No edit/delete
bulk_actions = [] # No bulk operations
Dashboard shows:
Dashboard Context Data¶
Project Dashboard Context¶
{
'app_list': [
{
'name': 'Webshop',
'app_label': 'webshop',
'verbose_name': 'Webshop',
'url': '/djadmin/webshop/',
'model_admins': [
{
'name': 'Product',
'display_name': 'Products',
'object_name': 'Product',
'general_actions': [...], # Action instances with URLs
'list_actions': [...], # Action instances with URLs
},
# ... more ModelAdmins
],
},
# ... more apps
],
'site_title': 'Django Admin Deux',
'site_header': 'Administration',
}
App Dashboard Context¶
{
'app_label': 'webshop',
'app_config': <AppConfig for webshop>,
'model_admins': [
{
'name': 'Product',
'display_name': 'Products',
'object_name': 'Product',
'general_actions': [...],
'list_actions': [...],
},
# ... more ModelAdmins
],
'site_title': 'Django Admin Deux',
'site_header': 'Administration',
}
Customizing Dashboard Templates¶
Override Project Dashboard¶
Create djadmin/project_dashboard.html in your template directory:
{% extends "djadmin/admin_base.html" %}
{% block title %}Dashboard{% endblock %}
{% block content %}
<h1>My Custom Dashboard</h1>
{% for app in app_list %}
<section class="app-section">
<h2>{{ app.verbose_name }}</h2>
{% for model_admin in app.model_admins %}
<div class="model-card">
<h3>{{ model_admin.display_name }}</h3>
<div class="actions">
{% for action in model_admin.general_actions %}
<a href="{{ action.url }}" class="{{ action.css_class }}">
{{ action.label }}
</a>
{% endfor %}
{% for action in model_admin.list_actions %}
<a href="{{ action.url }}" class="{{ action.css_class }}">
{{ action.label }}
</a>
{% endfor %}
</div>
</div>
{% endfor %}
</section>
{% endfor %}
{% endblock %}
Override App Dashboard¶
Create djadmin/app_dashboard.html:
{% extends "djadmin/admin_base.html" %}
{% block title %}{{ app_config.verbose_name }}{% endblock %}
{% block content %}
<h1>{{ app_config.verbose_name }}</h1>
{% for model_admin in model_admins %}
<div class="model-card">
<h2>{{ model_admin.display_name }}</h2>
<div class="actions">
{% for action in model_admin.general_actions %}
<a href="{{ action.url }}">{{ action.label }}</a>
{% endfor %}
</div>
</div>
{% endfor %}
{% endblock %}
Model-Specific Dashboard Cards¶
Create djadmin/<app>/<model>_dashboard_card.html for custom display:
{# djadmin/webshop/product_dashboard_card.html #}
<div class="product-card">
<h3>Products</h3>
<p>{{ product_count }} products in stock</p>
<div class="quick-stats">
<span>Active: {{ active_count }}</span>
<span>Low Stock: {{ low_stock_count }}</span>
</div>
<div class="actions">
{% for action in general_actions %}
<a href="{{ action.url }}">{{ action.label }}</a>
{% endfor %}
</div>
</div>
Navigation Between Dashboards¶
Breadcrumbs¶
Typical navigation pattern:
Home > Webshop > Products > Product List
│ │ │ └─ ListView
│ │ └─ Model Dashboard (if implemented)
│ └─ App Dashboard
└─ Project Dashboard
Links¶
{# In templates #}
<nav class="breadcrumbs">
<a href="{% url 'djadmin:index' %}">Dashboard</a>
<a href="{% url 'djadmin:app_index' app_label='webshop' %}">Webshop</a>
<span>Products</span>
</nav>
Best Practices¶
1. Use Meaningful General Actions¶
Provide clear entry points:
2. Keep Dashboard Clean¶
Don't overwhelm users with too many actions:
# Good - focused entry points
general_actions = [ListAction]
list_actions = [AddAction]
# Too much - cluttered dashboard
general_actions = [
ListAction, AnalyticsAction, ReportsAction,
ExportAction, ImportAction # Too many!
]
3. Group Related Models¶
Use app structure to group related ModelAdmins:
Webshop App
├── Products
├── Categories
├── Tags
└── Reviews
Orders App
├── Orders
├── OrderItems
└── Invoices
4. Multiple ModelAdmins for Different Users¶
Create role-specific views:
@register(Product)
class ManagerProductAdmin(ModelAdmin):
"""Full access for managers"""
list_display = ['name', 'sku', 'price', 'cost', 'margin']
general_actions = [ListAction]
@register(Product)
class StaffProductAdmin(ModelAdmin):
"""Limited view for staff"""
list_display = ['name', 'sku', 'price', 'stock_quantity']
general_actions = [ListAction]
list_actions = [] # Can't add
record_actions = [] # Can't edit/delete
5. Descriptive Model Meta¶
Use verbose names for better dashboard labels:
class Product(models.Model):
class Meta:
verbose_name = "Product"
verbose_name_plural = "Products" # Dashboard uses this
Common Patterns¶
Analytics Dashboard¶
class AnalyticsDashboardAction(GeneralActionMixin, BaseAction):
label = 'Analytics'
icon = 'chart'
@register(Product)
class ProductAdmin(ModelAdmin):
general_actions = [ListAction, AnalyticsDashboardAction]
Quick Add from Dashboard¶
Minimal Dashboard Entry¶
@register(Product)
class MinimalProductAdmin(ModelAdmin):
general_actions = [ListAction]
list_actions = []
record_actions = []
Troubleshooting¶
ModelAdmin Not Appearing in Dashboard¶
Problem: Registered ModelAdmin doesn't show in dashboard
Solution: Check that general_actions is not empty:
@register(Product)
class ProductAdmin(ModelAdmin):
general_actions = [ListAction] # Required for dashboard display
Too Many Dashboard Entries¶
Problem: Same model appears multiple times
Cause: Multiple @register() decorators create separate entries
Solution: This is by design. Each registration creates a separate ModelAdmin entry.
Actions Not Showing¶
Problem: Actions don't appear in dashboard
Solution: Verify action URLs are being generated:
See Also¶
- Basic Usage - ModelAdmin configuration
- Actions Guide - Understanding the action system
- Customization - Advanced customization
- Architecture - URL Routing - How URLs are generated