Dashboards with Apache ECharts¶
NewAdmin lets you replace the dashboard content with a Python class and a
template. Django admin still handles access, sessions, and native permissions.
You do not need to change ModelAdmin registrations or create another
AdminSite.
Enable a dashboard¶
Without extra settings, the dashboard shows authorized applications and recent activity. It does not load the chart library.
To enable the editorial example in the demo project:
NEWADMIN = {
"SITE_HEADER": "NewAdmin",
"DASHBOARD": "demo.catalog.dashboard.EditorialDashboard",
}
The demo requires its Article and Category models. A consumer project should
create its own provider instead of depending on demo models.
Write a provider¶
# news/admin_dashboard.py: example for a project with news.Article.
from django.db.models import Count
from newadmin.dashboard import EChartsDashboard
from .models import Article
class NewsDashboard(EChartsDashboard):
template_name = "news/admin/dashboard.html"
permissions = ("news.view_article",)
def get_context_data(self, request):
# For a multi-organization project, filter by user or organization here
# before aggregating. This example is for a single site.
articles = Article.objects.all()
counts = list(
articles.values("category__name")
.annotate(total=Count("pk"))
.order_by("-total")[:8]
)
rows = [[row["category__name"] or "Uncategorized", row["total"]]
for row in counts]
return {
"categories": {
"id": "news-categories",
"title": "Articles by category",
"description": "The eight categories with the most articles",
"columns": ["Category", "Articles"],
"rows": rows,
"option": {
"tooltip": {"trigger": "axis"},
"xAxis": {"type": "category", "data": [row[0] for row in rows]},
"yAxis": {"type": "value", "minInterval": 1},
"series": [{"name": "Articles", "type": "bar",
"data": [row[1] for row in rows]}],
},
},
}
# settings.py
NEWADMIN = {"DASHBOARD": "news.admin_dashboard.NewsDashboard"}
{% extends "newadmin/dashboard/layout.html" %}
{% block dashboard_title %}Editorial overview{% endblock %}
{% block dashboard_primary %}
{% include "newadmin/dashboard/chart.html" with chart=dashboard_data.categories %}
{% endblock %}
The provider receives request, is instantiated per request, and returns a
mapping. Its context is available under dashboard_data; it does not replace
permission, branding, session, or AdminSite application context. An invalid
import, incorrect class, or invalid context type raises ImproperlyConfigured.
permissions requires every listed permission before querying data or evaluating
Media. If the user lacks permission, the authorized generic dashboard appears.
Override has_permission(request) for additional rules. A model permission does
not automatically filter by organization or object; the provider must enforce
those rules in its querysets before aggregating or counting.
The custom dashboard applies to the main index. Application indexes, changelists, and forms keep their own screens and share the theme palette, header, and navigation. Selecting a provider changes only the dashboard content; no provider is needed to style the rest of the admin. Login and popups use the same palette in a compact frame.
Templates and components¶
newadmin/dashboard/layout.html exposes these blocks:
Block |
Purpose |
|---|---|
|
Dashboard title |
|
Actions with real URLs and permissions |
|
Main column, 8/12 from 1200 px |
|
Metrics column, 4/12 from 1200 px |
|
Full-width table or content |
|
Links, activity, or other follow-up content |
Blocks can include project templates, HTML tables, and Bootstrap components. The
layout stacks on mobile and uses the same light and dark styles. For a completely
different layout, template_name can point to another content template. It must
not include a complete HTML document or duplicate the admin frame.
The newadmin/dashboard/chart.html component accepts chart:
id: unique, valid HTML identifier.chart_idcan change it when reusing a chart.title: visible, accessible title.descriptionis optional.option: ECharts options serializable as JSON, without JavaScript functions.columns: headings for the tabular alternative.rows: rows of data presented by the chart.
Rows are required for the accessible alternative. If empty, the component shows
an empty state. It escapes cell HTML and uses json_script for data. The adapter
forces text tooltips, not HTML tooltips.
The newadmin/dashboard/metric.html component accepts metric with label,
value, share (actual percentage), tone (success, warning, or neutral),
and an optional chart. The demo calculates percentages from real counts. Its
sparklines show entries created in the last seven days, grouped by their current
status; they do not show status-change history.
Separate sites and resources¶
NEWADMIN = {
"DASHBOARD": "news.admin_dashboard.NewsDashboard",
"SITES": {"operations": {"DASHBOARD": None}},
}
SITES keys are AdminSite instance names. None keeps the generic dashboard
for that site. Providers do not share instances or data between requests.
You can subclass Dashboard for a panel without ECharts. EChartsDashboard
includes the local runtime and adapter. A Media class adds custom CSS or
JavaScript and keeps inherited resources through Django’s native mechanism:
class NewsDashboard(EChartsDashboard):
# ...
class Media:
css = {"all": ["news/dashboard.css"]}
js = ["news/dashboard.js"]
In Django 6.1, Media rendering uses Django’s native nonce mechanism when the
context provides one. A specific CSP policy and consumer customizations need
their own review; enabling unsafe-eval is not required.
Behavior and limits¶
Charts use SVG and resize with their container. They respect light/dark/auto mode and reduced-motion preferences.
Changing theme keeps legend selection and zoom range.
ECharts provides ARIA descriptions; tabular data remains available without JavaScript. This alone does not certify keyboard access or full WCAG compliance.
The adapter initializes charts present at page load. If a project inserts charts dynamically, it must manage their lifecycle with its own JavaScript and the ECharts API.
Initialization errors are logged in the console, and tabular data remains available. There are no CDN or export-service requests.
The theme does not create automatic queries for arbitrary models. Providers choose filters, aggregations, limits, and business rules.
Distribution and development¶
ECharts 6.1.0 is pinned in npm. The Python package includes its compiled runtime, LICENSE, NOTICE, and notices for d3, zrender, and tslib. There is no license fee to enable these charts. Keep those notices when redistributing the resources.
npm ci
npm run build:charts
npm run build:css
These commands are for theme development. Installing the wheel does not require Node. The full ECharts build is distributed to support consumer chart types; it is about 1.1 MB minified and loads only when the provider declares those assets.
References: ECharts options, themes, license.