Skip to main content

ModelAdmin

Added in 1.0.1

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​

Changed in 1.0.7

Pass _return_url in the change-form query string when the Back button should return to another internal page. Chassis accepts relative and same-host URLs, rejects external hosts, and ignores a return URL that points back to the same change form.

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 │
│ RelatedCollectionsOption inputs with add/delete controls │
├─ related entities (`after_field_sets`) ───────────────────┤
│ One fieldset per RelatedEntityOption (paginated table) │
├─ submit row ──────────────────────────────────────────────┤
│ [Save] [Back] [Delete] │
└───────────────────────────────────────────────────────────┘

The submit row uses the shared right-aligned action panel and Back button. Required fields receive a consistent red marker, while required confirmation checkboxes use full-width labels and appear after other fields. Validation errors are summarized above the form in the common danger alert.

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​

  1. Walk self.options and return the first instance of the requested type.
  2. If none, walk ChassisAdminMixin.options (today: a default RowActionsOption()).
  3. 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:

  • SearchOption
  • FiltersOption
  • DateHierarchyOption
  • FieldTabsOption
  • ForeignKeyTabsOption
  • BadgeFieldsOption
  • CopyableFieldsOption
  • DecimalAmountOption
  • RelatedFieldsOption
  • RelatedCollectionsOption
  • PrettyJsonOption
  • RowActionsOption
  • ListActionsOption
  • ObjectActionsOption
  • RelatedEntitiesOption
  • ImportOption
  • ExportOption

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.

ParameterDefaultPurpose
search_collapsedTrueStart with the search fieldset collapsed
date_hierarchy_collapsedTrueCollapse the date hierarchy fieldset
filters_collapsedTrueCollapse the filters fieldset
allow_standard_addTrueWhen False, has_add_permission() is False

Other mixin attributes​

AttributeDefaultPurpose
change_list_templateadmin/chassis/change_list.htmlChassis changelist
change_form_templateadmin/chassis/change_form.htmlChassis change form
chassis_link_first_columnFalseFirst 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 delete
  • NoDeleteAdminMixin — 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.

See also​