Skip to main content

Dashboard

Added in 1.0.1

The Admin index is a dashboard. You declare components and place them in blocks on a four-column grid. DashboardService validates the layout and renders SSR context. Live widgets refresh through dashboard/live/.

Index template: admin/chassis/dashboard/index.html (extends admin/index.html). Set index_template only if you replace the whole page.

Page anatomy

┌─ navbar (theme, custom buttons, page-group dropdowns, user menu) ─┐
├─ sidebar (declared sidebar_items) ─────────────────────────────────┤
├─ alert strip (`nav-breadcrumbs` override) ─────────────────────────┤
│ global / alert blocks (`is_global=True`, ALERTS only) │
├─ main grid (`admins-dashboard-layout`) ────────────────────────────┤
│ row 1: block size 2 + block size 2 │
│ row 2: block size 4 (full width) │
│ … │
│ optional aside: Django "Recent actions" (`show_recent_actions`) │
└────────────────────────────────────────────────────────────────────┘

Each block includes templates/admin/chassis/dashboard/sections/*.html for its DashboardBlockType. Charts load ApexCharts. Live widgets poll {% url 'admin:dashboard_live' %} with If-None-Match.

If dashboard_component_classes is empty, the shell still renders: brand, sidebar, navbar, and an empty grid.

Components and blocks

from django.utils.translation import gettext_lazy as _

from django_chassis.dto import DashboardBlockDTO
from django_chassis.enums import DashboardBlockType


class CustomAdminSite(ChassisAdminSiteMixin, AdminSite):
dashboard_component_classes = (OpenOrdersMetric, RevenueChart, NightlyImportAlert, RebuildSearchAction)
dashboard_blocks = (
DashboardBlockDTO(
slug='alerts',
title=_('Alerts'),
block_type=DashboardBlockType.ALERTS,
component_slugs=('nightly-import',),
row=1,
size=4,
is_global=True,
),
DashboardBlockDTO(
slug='kpis',
title=_('Overview'),
block_type=DashboardBlockType.METRICS,
component_slugs=('open-orders',),
row=2,
size=2,
),
DashboardBlockDTO(
slug='revenue',
title=_('Revenue'),
block_type=DashboardBlockType.CHART,
component_slugs=('revenue',),
row=2,
size=2,
),
)

DashboardBlockDTO

ParameterTypeDefault
slugunique block idrequired
titlelocalized stringrequired
block_typeDashboardBlockTyperequired
component_slugsslugs of components in this blockrequired
rowgrid row1
grouplayout group'default'
size1–4 columns4
ordersort inside the row100
is_globalspan the full widthFalse

DashboardBlockType: alerts, metrics, actions, metrics_and_actions, chart.

Layout rules

  • The grid is four columns.
  • A chart block contains exactly one chart.
  • A component slug cannot be assigned twice.
  • Only alert blocks may set is_global=True.
  • Unknown slugs and empty component_slugs fail validation.

Live endpoint

GET {admin}/dashboard/live/ returns the current widget snapshot. Send If-None-Match to receive 304 when the ETag has not changed. DashboardLiveSerializationService builds deterministic ETags.

Widgets carry etag, fetched_at, and next_refresh_at when the component provides them.

Visibility

Every component inherits:

  • slug, label, order, status
  • check_view(request) / check_use(request)
  • is_visible / is_available — superusers see and use everything; HIDDEN hides the widget; non-ACTIVE status blocks use

See Dashboard metrics and charts for the concrete component contracts.

See also