Skip to main content

Core framework for Django Control Room panels

Project description

Django Control Room Panel Tests codecov PyPI version Python versions License: MIT

dj-control-room-base

dj-control-room-base - a core library for creating DCR panels

dj-control-room-base is a core library for Django Control Room panels. It provides the shared primitives that every panel needs: settings management, CSS injection, permission enforcement, admin sidebar integration, and template context helpers.

Official Django Control Room panels ship with this package as a dependency and build on these APIs rather than reimplementing them panel by panel.

Optionally, the package can also be mounted as a full panel in its own right: it ships a bundled design system reference UI and example patterns that are useful when building or theming new panels.

What this library provides

Centralized CSS and permissions

The main value of this library is that it centralizes the settings every panel would otherwise duplicate independently. A single PanelConfig object, instantiated once in a panel's conf.py, handles:

  • CSS injection - whether to load the shared design-system bundle, and any additional stylesheets, resolved and injected into template context automatically
  • Permission enforcement - staff checks, optional superuser-only restriction, Django group allow lists, and per-view scope overrides, all driven from the same merged settings dict
  • Settings merging - panel-level defaults, hub overrides from dj-control-room, and project-level settings are merged in a defined precedence order so each layer can override only what it needs

Panel authors who use PanelConfig get all of this for free. See CSS and permissions below for the full reference.

Admin sidebar integration

PanelPlaceholderModel and BasePanelAdmin give any panel a Django admin sidebar entry that redirects to the panel's main view, with no writable actions, no migrations, and automatic respect for the same permission rules configured on PanelConfig.

Template context helpers

panel_config.get_context(request, title="...") returns a fully-prepared context dict that includes the standard Django admin context, CSS injection variables, and any extra kwargs you pass. No manual assembly required.

Entry-point discovery

Panels register themselves with Control Room via a pyproject.toml entry point under dj_control_room.panels. This library ships the reference implementation of that pattern.

The only runtime dependency is Django. dj-control-room is optional and only needed for the centralized hub dashboard.

Screenshots

Django admin - the placeholder model registers an app entry that redirects to the panel, with no extra migrations required:

Django admin home showing the DJ Control Room Base sidebar entry

The panel UI - the bundled design system reference view, accessible at /admin/dj-control-room-base/:

DJ Control Room Base design system panel view

Requirements

  • Python 3.9+
  • Django 4.2+ (tested in CI across Django 4.2, 5.2, and 6.0)

Project layout

dj-control-room-base/
├── dj_control_room_base/
│   ├── core/              # PanelConfig, BasePanelAdmin, PanelPlaceholderModel
│   ├── templates/         # Panel templates
│   ├── static/            # Design system CSS and assets
│   ├── conf.py            # PanelConfig instance + settings key
│   ├── panel.py           # Control Room entry-point panel class
│   ├── views.py
│   ├── urls.py
│   ├── admin.py
│   └── models.py          # Placeholder model for admin sidebar
├── example_project/       # Runnable demo + pytest settings
├── tests/
├── mkdocs.yml             # Documentation site
└── requirements.txt       # Dev / demo deps (includes dj-control-room)

Quick start

pip install dj-control-room-base
# settings.py
INSTALLED_APPS = [
    ...
    "dj_control_room_base",
]
# urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path("admin/dj-control-room-base/", include("dj_control_room_base.urls")),
    path("admin/", admin.site.urls),
]
python manage.py migrate
python manage.py runserver

Open /admin/ and sign in. A DJ CONTROL ROOM BASE entry appears in the sidebar and links to the panel at /admin/dj-control-room-base/.

See the full documentation for installation options, configuration reference, and a guide for building your own panel on this library.

Django Control Room dashboard

  1. Add dj_control_room to INSTALLED_APPS (with dj_control_room_base).
  2. Include path("admin/dj-control-room/", include("dj_control_room.urls")) as above.
  3. Open /admin/dj-control-room/ to see registered panels (this package advertises itself via the dj_control_room.panels entry point).

Panel metadata (name, description, icon, docs/PyPI links) lives in dj_control_room_base/panel.py; customize a fork or your own panel package the same way.

CSS and permissions

PanelConfig is the central object that every panel built on this library uses. Instantiate it once in conf.py with a settings key and panel-level defaults, then call its helpers from views, templates, and the admin class. The same config object drives CSS injection, permission checks, and the full template context.

Settings merge order

Settings are resolved fresh on every call so that runtime changes (e.g. from the Control Room hub) are always picked up. The merge order is, from lowest to highest priority:

  1. Built-in defaults (PANEL_BUILTIN_DEFAULTS in core/panel_config.py) - CSS and permission keys that every panel gets automatically, even if the panel author never declares them.
  2. Panel defaults - the defaults dict passed to PanelConfig(...) in the panel's own conf.py.
  3. Hub overrides - injected at runtime by dj-control-room via apply_override_settings() when the hub is installed. Lets the hub enforce global CSS or permission policies across all panels from a single place.
  4. Project settings - the dict at settings.DJ_<PANEL>_SETTINGS in the consuming Django project. These win over everything, so a project can always opt out of hub defaults.

The result is that panel authors declare a minimal defaults, project owners override only what they need, and the hub can push cross-panel policy without touching individual panel settings files.

CSS settings

Key Type Default Effect
LOAD_DEFAULT_CSS bool True Loads the shared design-system.css bundle from this package. Set to False if the hub or a parent template already loads it.
EXTRA_CSS list[str] [] Additional stylesheets to inject. Relative paths are resolved through Django's staticfiles; absolute URLs (http://, https://, //) are used as-is.

In a view, call panel_config.get_context(request, title="My Panel") to get a context dict that already contains dj_cr_load_default_css and dj_cr_extra_css alongside the standard Django admin context. Templates use these to inject the right <link> tags without any per-view wiring.

Permission settings

Panels built on this library follow a two-level permission model: a panel-wide policy, and optional per-scope overrides for individual views.

Panel-wide keys (apply to all views unless a scope overrides them):

Key Type Default Effect
ALLOWED_GROUPS list[str] [] Django group names that may access the panel. Empty list means any staff user is allowed.
REQUIRE_SUPERUSER bool False Restricts the panel to superusers only.

Per-view scopes (SCOPE_PERMISSIONS):

A scope is a string label that matches the argument passed to @panel_config.permission_required("my-scope") on a view. Each scope entry accepts the same ALLOWED_GROUPS and REQUIRE_SUPERUSER keys and overrides the panel-wide values for that view only.

"SCOPE_PERMISSIONS": {
    "reports": {"REQUIRE_SUPERUSER": True},     # only superusers
    "dashboard": {"ALLOWED_GROUPS": ["ops"]},   # ops group only
    "status": {},                               # inherits panel-wide policy
}

Resolution rules (applied in order):

  1. The user must be authenticated and staff. Anonymous users are redirected to the Django admin login.
  2. Superusers always pass (they bypass group checks, matching Django admin behaviour).
  3. If REQUIRE_SUPERUSER is True for the resolved scope, non-superusers receive a 403.
  4. If ALLOWED_GROUPS is non-empty, the user must belong to at least one of those groups (checked by name). An empty list skips the group check.

Using it in a panel

# myapp/conf.py
from dj_control_room_base.core import PanelConfig

panel_config = PanelConfig(
    settings_key="DJ_MY_PANEL_SETTINGS",
    defaults={
        "LOAD_DEFAULT_CSS": True,
        "EXTRA_CSS": [],
    },
)

# myapp/views.py
from .conf import panel_config

@panel_config.permission_required("dashboard")
def dashboard(request):
    context = panel_config.get_context(request, title="Dashboard")
    return render(request, "mypanel/dashboard.html", context)

That is the entirety of the wiring. Permission enforcement, login redirect, CSS injection, and the Django admin context are all handled by the two panel_config calls.

Building your own panel on this package

Import primitives from dj_control_room_base.core:

  • PanelConfig - Instantiate in conf.py with your settings key and defaults; use get_context, permission_required, and CSS helpers in views.
  • PanelPlaceholderModel - Abstract managed=False base for a sidebar-only model.
  • BasePanelAdmin - Redirect changelist to your namespace:index URL; set panel_config for aligned permissions.

Copy the entry-point pattern from pyproject.toml:

[project.entry-points."dj_control_room.panels"]
my_panel = "my_panel.panel:MyPanel"

Development

Clone and install in editable mode with dev dependencies:

git clone https://github.com/yassi/dj-control-room-base.git
cd dj-control-room-base
python -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate
make install                # pip install -r requirements.txt && pip install -e .

Run tests locally (uses SQLite by default via example_project settings):

make test_local
# or: python -m pytest tests/ -v

Coverage:

make test_coverage

Docker Compose provides a dev container (app on port 8000) and optional Postgres. From the repo root:

make docker_up
make docker_shell    # working directory: /app/example_project

Inside the container you can run python manage.py runserver 0.0.0.0:8000 or pytest. For Postgres-backed runs, set DB_ENGINE=postgresql and point host/user/password at the postgres service.

Documentation:

make docs          # mkdocs build
make docs_serve    # local preview

License

MIT. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dj_control_room_base-0.1.1.tar.gz (111.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dj_control_room_base-0.1.1-py3-none-any.whl (118.1 kB view details)

Uploaded Python 3

File details

Details for the file dj_control_room_base-0.1.1.tar.gz.

File metadata

  • Download URL: dj_control_room_base-0.1.1.tar.gz
  • Upload date:
  • Size: 111.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dj_control_room_base-0.1.1.tar.gz
Algorithm Hash digest
SHA256 94c5de0f94edd89b6956d895c2fd7dd6a08edd96b4db738475d7f2356c2a2835
MD5 eb7ad9b9191880c71c5205459210a591
BLAKE2b-256 7073d980d1d568593dd624ec84873b06a789e8533ea58384a61df77ca10ba6bd

See more details on using hashes here.

Provenance

The following attestation bundles were made for dj_control_room_base-0.1.1.tar.gz:

Publisher: python-publish.yml on yassi/dj-control-room-base

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dj_control_room_base-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for dj_control_room_base-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 efbb6ec9c0a21c62a12ca99663e004c13824d68cdb0ef69ebb722bddfbb546f5
MD5 36067fc8b91fa979df7d8ab8f652db22
BLAKE2b-256 0b79af89ef61d9187f01e841e404e57e2af39c37eb19821995a52b383f276bed

See more details on using hashes here.

Provenance

The following attestation bundles were made for dj_control_room_base-0.1.1-py3-none-any.whl:

Publisher: python-publish.yml on yassi/dj-control-room-base

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page