How it works
Chassis is a thin assembly layer over Django Admin. You declare capabilities. Services turn those declarations into URLs, template context, and permission checks. Templates and static files render the result.
Two mixins
The public entry points are ChassisAdminSiteMixin and ChassisAdminMixin.
ChassisAdminSiteMixin + AdminSite
├── dashboard_component_classes / dashboard_blocks → DashboardService
├── navbar_button_classes / user_menu_item_classes → AdminNavbarService
├── chassis_page_classes → AdminPageService
├── sidebar_items → AdminSidebarService
└── wraps third-party ModelAdmin classes in ChassisAdminMixin
ChassisAdminMixin + ModelAdmin
└── options: list[AdminOption]
├── SearchOption, FiltersOption, DateHierarchyOption, tabs
├── RowActionsOption, ListActionsOption, ObjectActionsOption
├── RelatedEntitiesOption
└── ImportOption, ExportOption
Both mixins must precede the Django class in the MRO so their hooks can wrap
super().
Internal ModelAdmin composition
django_chassis.mixins.admin remains the public module for
ChassisAdminMixin. Its implementation is assembled from focused classes in
django_chassis.mixins.core:
AdminCoreMixin— shared options and typed access to the nextModelAdminAdminPermissionsMixinandAdminAuditMixin— access and CRUD audit hooksAdminChangeListMixinandAdminObjectPageMixin— list and object pagesAdminActionsMixinandAdminImportExportMixin— actions and data flowsAdminPresentationMixin— dynamic fields, columns, and widgets
These classes are implementation parts. Applications continue to inherit only
ChassisAdminMixin; its public import paths and position in the application
MRO do not change.
Model managers
Django model Manager and QuerySet classes live in
django_chassis.models.managers. Model modules contain model declarations and
attach the imported manager; they do not define query infrastructure inline.
Frozen options
A ModelAdmin does not subclass a dozen mixins for search, badges, and
export. It appends frozen dataclasses to options. ChassisAdminMixin looks up each
type, applies it to Django Admin attributes (search_fields, list_filter,
…), and feeds the rest to templates.
Missing option types fall back to the mixin default. Today that default is
RowActionsOption() — a view button on every changelist.
Settings is not an AdminOption. It is a separate dataclass on
chassis_settings for collapsed fieldsets and whether the standard add button
is shown.
Services
Site-level work is not done in views. The site constructs services:
| Service | Responsibility |
|---|---|
DashboardService | Component registry, layout validation, SSR context, live JSON |
AdminNavbarService | Theme item, custom buttons, page groups, user menu |
AdminPageService | Page routes and navbar/dashboard groups |
AdminSidebarService | Resolve model/page references, permissions, active state |
You can replace a service class on the site (dashboard_service_class, …) or
override get_*_service().
Request path
- Django routes the request to the Chassis
AdminSite. each_contextinjects brand, sidebar, navbar, and footer into every Admin template.- Index (
/):DashboardServicemapsdashboard_blocksonto component slugs and rendersadmin/chassis/dashboard/index.html. Live widgets polldashboard/live/withIf-None-Match. - Changelist:
ChassisAdminMixin.changelist_viewreads options, builds tabs / search / filters / list actions, and rendersadmin/chassis/change_list.html. - Change form:
changeform_viewadds object-action buttons and related entity tables (admin/chassis/change_form.html). - Custom page:
AdminPage.dispatchchecks the access contract, thenview()/render(). - Object action / import / export: extra URLs from
ChassisAdminMixin.get_urls().
A missing option type is not an error. The mixin uses the class-level
default (RowActionsOption()) or skips that chrome (no search fieldset
without SearchOption).
Templates
'django_chassis' must sit before 'django.contrib.admin' in
INSTALLED_APPS. Chassis ships a full overlay of Admin templates plus a
parallel admin/tabler/ family. Domain apps should not copy those templates.
See Theming.
What Chassis does not do
- It does not own your models.
- It does not replace Django permissions; it checks them.
- It does not invent a new admin URL scheme. Custom pages and dashboard
actions are extra routes on the same
AdminSite.