ModelAdmin
ChassisAdminMixin is the ModelAdmin entry point. Put it first in the MRO. Attach
capabilities through options.
from django.contrib.admin import ModelAdmin
from django_chassis.mixins import ChassisAdminMixin
from django_chassis.options import RowActionsOption, SearchOption, Settings
class BookAdmin(ChassisAdminMixin, ModelAdmin):
chassis_settings = Settings(search_collapsed=True, allow_standard_add=True)
options = [SearchOption(fields=['title']), RowActionsOption()]
MRO
class BookAdmin(ChassisAdminMixin, ModelAdmin): # correct
...
class BookAdmin(ModelAdmin, ChassisAdminMixin): # wrong — hooks will not wrap super()
...
The same rule applies to ReadOnlyAdminMixin and NoDeleteAdminMixin: they
must sit where their has_*_permission overrides still run.
Change-form anatomy
Template: admin/chassis/change_form.html (extends
admin/change_form.html).
┌─ breadcrumbs ─────────────────────────────────────────────┐
│ Dashboard › Section › Model › object │
├─ toolbar (`page_actions`) ────────────────────────────────┤
│ [@object_action buttons…] [Django history / …] │
├─ Django fieldsets / inlines ──────────────────────────────┤
│ Pretty JSON / decimal widgets / date masks │
├─ related entities (`after_field_sets`) ───────────────────┤
│ One fieldset per RelatedEntityOption (paginated table) │
├─ submit row ──────────────────────────────────────────────┤
│ [Save] [Back] [Delete] │
└───────────────────────────────────────────────────────────┘
Object actions require ObjectActionsOption plus @object_action on the
methods. Related tables require RelatedEntitiesOption. See
Object actions and
Related entities.
The first column of the changelist is not a link by default. Users
reach this page through a row action (RowActionType.VIEW or CHANGE).
How get_chassis_option resolves
- Walk
self.optionsand return the first instance of the requested type. - If none, walk
ChassisAdminMixin.options(today: a defaultRowActionsOption()). - Composite things (several FK groups, several row actions) live inside one option object.
There is no merging of two SearchOption instances. The local one wins.
options
options is a list of frozen dataclasses. Do not rename this attribute.
Full field tables, validation, and UI regions: Options catalog.
AdminOption is the union of:
SearchOptionFiltersOptionDateHierarchyOptionFieldTabsOptionForeignKeyTabsOptionBadgeFieldsOptionDecimalAmountOptionPrettyJsonOptionRowActionsOptionListActionsOptionObjectActionsOptionRelatedEntitiesOptionImportOptionExportOption
The mixin default is [RowActionsOption()]. If you set options yourself,
include RowActionsOption when you still want the last-column buttons.
Settings
Not an option. Assigned to chassis_settings.
| Parameter | Default | Purpose |
|---|---|---|
search_collapsed | True | Start with the search fieldset collapsed |
date_hierarchy_collapsed | True | Collapse the date hierarchy fieldset |
filters_collapsed | True | Collapse the filters fieldset |
allow_standard_add | True | When False, has_add_permission() is False |
Other mixin attributes
| Attribute | Default | Purpose |
|---|---|---|
change_list_template | admin/chassis/change_list.html | Chassis changelist |
change_form_template | admin/chassis/change_form.html | Chassis change form |
chassis_link_first_column | False | First column is not a change-link |
Row actions are the intended entry point into an object. Set
chassis_link_first_column = True only if you want Django's classic first
column link.
Companion mixins
ReadOnlyAdminMixin— deny add, change, and deleteNoDeleteAdminMixin— deny delete
Put the denial mixin before ChassisAdminMixin when its has_*_permission
overrides must win:
class LogAdmin(ReadOnlyAdminMixin, ChassisAdminMixin, ModelAdmin):
options = [SearchOption(fields=['message'])]
System checks
ChassisAdminMixin runs checks for action permissions and export lookups. Failures
show up as Django system checks, not silent template gaps.