Options catalog
Every Chassis capability is a frozen dataclass. You do not subclass a
mixin for search, another for badges, and another for export. You append
option objects to ModelAdmin.options or assign site-level options on
ChassisAdminSiteMixin.
This page is the full catalog: purpose, fields, defaults, validation, and which UI region each option drives.
How lookup works
ChassisAdminMixin.get_chassis_option(option_class=...) returns the first
instance of that type on the local options list. If the local list has no
match, it falls back to ChassisAdminMixin.options, which is
[RowActionsOption()].
Consequences:
- At most one instance of each option type is used. Put several FK tab groups
inside one
ForeignKeyTabsOption, not as three sibling options. - If you set
options = [SearchOption(...)]and omitRowActionsOption, the mixin still injects the default view button from the class-level list. - To hide row actions, pass
RowActionsOption(actions=[]). Settingsis not anAdminOption. Assign it tochassis_settings.
Do not rename the options attribute.
AdminOption union
These types are legal on ModelAdmin.options:
| Option | Page region |
|---|---|
SearchOption | Changelist search fieldset |
FiltersOption | Changelist filter fieldset |
DateHierarchyOption | Changelist date drill-down |
FieldTabsOption | Changelist choice tabs |
ForeignKeyTabsOption | Changelist FK tabs |
BadgeFieldsOption | Changelist badge columns |
CopyableFieldsOption | Read-only values with copy buttons |
PrettyJsonOption | Change form / list JSON |
DecimalAmountOption | Integer money as Decimal |
RelatedFieldsOption | Read-only values from related model paths |
RelatedCollectionsOption | Editable values stored in a dependent model |
RowActionsOption | Last changelist column |
ListActionsOption | Changelist toolbar |
ObjectActionsOption | Change-form toolbar |
RelatedEntitiesOption | Change-form related tables |
ImportOption | Import flow + toolbar button |
ExportOption | Export flow + toolbar button |
Nested types (RowActionOption, TableColumnOption, …) are not
AdminOption members. They live inside a parent option.
Site-level types (Sidebar*, AdminPageGroupOption, PermissionOption)
are assigned on the AdminSite, not on options.
Settings
Not an option. Assigned to chassis_settings on a ModelAdmin or AdminPage.
from django_chassis.options import Settings
chassis_settings = Settings(
search_collapsed=True, date_hierarchy_collapsed=True, filters_collapsed=True, allow_standard_add=True
)
| Field | Type | Default | Effect |
|---|---|---|---|
search_collapsed | bool | True | Search fieldset starts collapsed |
date_hierarchy_collapsed | bool | True | Date hierarchy starts collapsed |
filters_collapsed | bool | True | Filters fieldset starts collapsed |
allow_standard_add | bool | True | Show Django's Add button in the changelist toolbar |
allow_standard_add=False makes has_add_permission() return False, so
the standard Add button disappears. List actions and import/export buttons
are unaffected.
SearchOption
Puts Django search_fields into a Chassis fieldset above the result table.
The mixin writes search_fields onto the instance so Django's own
checks still see them.
from django_chassis.options import SearchOption
SearchOption(fields=['title', 'isbn', 'author__name'], fieldset_title='Search', placeholder='Title, ISBN, or author')
| Field | Type | Default | Required |
|---|---|---|---|
fields | list[str] | — | yes |
fieldset_title | str or gettext lazy | _('Поиск') | no |
placeholder | str or gettext lazy | '' | no |
fields uses Django search lookups (icontains by default, ^ prefix,
= exact, @ full text — same as stock Admin).
Without this option the changelist has no search fieldset.
FiltersOption
Renders Chassis select-filters in their own fieldset. fields is assigned
to Django list_filter.
from django.contrib.admin import SimpleListFilter
from django_chassis.options import FiltersOption
FiltersOption(fields=['status', 'author', PublishedThisYearFilter], fieldset_title='Filters')
| Field | Type | Default | Required |
|---|---|---|---|
fields | list[Any] | — | yes |
fieldset_title | localized string | _('Фильтры') | no |
Accepted values are the same as Django list_filter: field names, related
lookups, and SimpleListFilter subclasses.
The stock Django right-hand filter sidebar is suppressed
({% block filters %}{% endblock %}). Filters live in the Chassis controls
stack above the table.
DateHierarchyOption
Enables Django date_hierarchy and wraps it in a Chassis fieldset.
from django_chassis.options import DateHierarchyOption
DateHierarchyOption(field='published_at', fieldset_title='Dates')
| Field | Type | Default | Required |
|---|---|---|---|
field | str | — | yes — DateField / DateTimeField name |
fieldset_title | localized string | _('Даты') | no |
The mixin writes date_hierarchy on the instance for Django checks.
FieldTabsOption
Tabs (or a <select>) that filter the changelist by a choices field on
the current model. Each tab is a query-string link; "All" clears the filter.
from django_chassis.enums import TabDisplay
from django_chassis.options import FieldTabsOption
FieldTabsOption(
field='status', choices=Book.Status.choices, display=TabDisplay.BUTTONS, all_label='All', fieldset_title='Status'
)
| Field | Type | Default | Required |
|---|---|---|---|
field | str | — | yes |
choices | list[tuple[Any, Any]] | — | yes — (value, label) pairs |
display | TabDisplay | TabDisplay.BUTTONS | no |
all_label | localized string | _('Все') | no |
fieldset_title | localized string | _('Tabs') | no |
TabDisplay.BUTTONS renders a row of links. TabDisplay.SELECT renders a
dropdown that navigates on change.
Use this when the dimension is a local choices field. Use
ForeignKeyTabsOption when the dimension is a related model.
ForeignKeyTabsOption
Changed in 1.0.9
One or more tab groups, each bound to a ForeignKey on the current model. Every related object that appears in the queryset becomes a tab.
from django_chassis.options import ForeignKeyTabGroupOption, ForeignKeyTabsOption
ForeignKeyTabsOption(
groups=[
ForeignKeyTabGroupOption(field='author', model=Author, label='Authors', all_label='All authors'),
ForeignKeyTabGroupOption(field='publisher', model=Publisher, label='Publishers'),
],
display=TabDisplay.BUTTONS,
fieldset_title='Relations',
)
Single-group shortcut
ForeignKeyTabsOption(field='author', model=Author)
is equivalent to one ForeignKeyTabGroupOption in groups.
| Field | Type | Default | Required |
|---|---|---|---|
groups | list[ForeignKeyTabGroupOption] | [] | one of groups or field+model |
field | str or None | None | shortcut |
model | model class or None | None | shortcut |
display | TabDisplay | BUTTONS | no |
all_label | localized string | _('Все') | no |
fieldset_title | localized string | _('Tabs') | no |
queryset_filters | dict[str, object] | {} | no — shortcut choice filter |
ForeignKeyTabGroupOption
| Field | Type | Default | Required |
|---|---|---|---|
field | FK field name on the current model | — | yes |
model | related model class | — | yes |
label | localized string | '' | no — group heading |
all_label | localized string | _('Все') | no |
queryset_filters | dict[str, object] | {} | no — passed to model.objects.filter() |
You cannot attach two ForeignKeyTabsOption objects. Put every group in
groups. Use queryset_filters, for example {'is_active': True}, to omit
related objects that should not appear as available tabs.
BadgeFieldsOption
Changed in 1.0.17
Renders named changelist columns as colored badges. The mixin replaces each
listed field in list_display with a generated display method. Badge text
always stays on one line, including labels containing multiple words.
from django_chassis.enums import ButtonColor
from django_chassis.options import BadgeFieldsOption
BadgeFieldsOption(
fields=['status', 'kind'],
colors={'status': {'active': ButtonColor.SUCCESS, 'draft': ButtonColor.SECONDARY, 'archived': ButtonColor.WARNING}},
)
| Field | Type | Default | Required |
|---|---|---|---|
fields | list[str] | — | yes |
colors | Mapping[str, Mapping[object, ButtonColor]] | {} | no |
A missing color mapping uses the default badge tone. Keys of the inner mapping are the raw field values (enum members, strings, booleans).
ButtonColor: primary, secondary, success, warning, danger,
info.
CopyableFieldsOption
Added in 1.0.7
Changed in 1.0.11
Replaces named fields in changelists and change forms with escaped read-only inputs and attached clipboard buttons.
from django_chassis.options import CopyableFieldsOption
CopyableFieldsOption(
fields=['address', 'external_id', 'api_token'],
editable_on_add=True,
masked_fields=['api_token']
)
| Field | Type | Default | Required |
|---|---|---|---|
fields | list[str] | — | yes — unique names |
editable_on_add | bool | False | no — preserve the source input while creating an object |
masked_fields | list[str] | [] | no — fields whose visible values keep only the first and last two characters |
Generated display name: chassis_copyable_<field>. Sorting still uses the
source field. Duplicate names raise
ValueError('Chassis copyable field names must be unique.').
When editable_on_add=True, list pages remain copyable, the add form renders
the original editable field, and later change forms render its copyable
read-only representation.
Fields in masked_fields render a masked input, while the copy button writes
the original value. The original must still be delivered to an authorized
browser for clipboard copying, so masking is a presentation feature rather
than an access-control boundary.
PrettyJsonOption
Builds a read-only pretty_<field> display method for each JSON field and
highlights it with Pygments. Domain ModelAdmins do not declare those methods
by hand.
from django_chassis.options import PrettyJsonOption
PrettyJsonOption(fields=['payload', 'metadata'])
| Field | Type | Default | Required |
|---|---|---|---|
fields | list[str] | — | yes |
Put the original field name in list_display / readonly_fields if you
want the pretty column on the changelist or change form. The mixin installs
the method at __init__ time.
DecimalAmountOption
Displays integer minor-unit amounts as Decimal using two methods on the model:
_get_fraction_number(...)convert_amount_to_decimal(...)
If available, convert_amount_field_to_decimal(field_name=..., amount=...)
takes precedence so each configured field can resolve its own currency or
asset context.
If either method is missing, the option is silently ignored (no column
rewrite). If a listed name is not an IntegerField, construction raises
ImproperlyConfigured.
from django_chassis.options import DecimalAmountOption
DecimalAmountOption(fields=['amount', 'fee'])
| Field | Type | Default | Required |
|---|---|---|---|
fields | list[str] | — | yes — unique integer field names |
Duplicate names raise ValueError('Chassis decimal amount field names must be unique.').
Generated list-display name: chassis_decimal_<field>. Sorting still uses
the underlying integer.
RelatedFieldsOption / RelatedFieldOption
Added in 1.0.8
Changed in 1.0.9
Creates read-only displays from a model attribute or a Django relation path.
The same source path is used in list_display and/or fieldsets; Chassis
registers the display method under that path and adds it to readonly_fields.
from django.utils.translation import gettext_lazy as _
from django_chassis.options import RelatedFieldOption, RelatedFieldsOption
RelatedFieldsOption(fields=[
RelatedFieldOption(
field='wallet_pool__currency__name',
label=_('Currency'),
help_text=_('Currency assigned to the wallet pool.'),
empty_value_display=_('Not assigned')
),
])
RelatedFieldsOption
| Field | Type | Default | Required |
|---|---|---|---|
fields | list[RelatedFieldOption] | — | yes — unique paths |
RelatedFieldOption
| Field | Type | Default | Required |
|---|---|---|---|
field | str | — | yes — valid __ relation path or model attribute |
label | str | Promise | — | yes; pass _('…') for localization |
help_text | str | Promise | None | None | no |
empty_value_display | str | Promise | None | None | no — overrides the ModelAdmin placeholder |
When help_text is set, the shared immediate tooltip opens from the whole
header on hover or from the icon on keyboard focus. Chassis uses
select_related for single relations and prefetch_related for reverse or
many-valued relations. A many-valued path renders every value instead of
choosing an arbitrary first row and is not sortable. A concrete single field
retains Django formatting and ordering; Decimal values use fixed-point output.
When the same field is also configured by DecimalAmountOption, the Decimal
conversion remains active and uses this option's label and help tooltip.
When it is also configured by CopyableFieldsOption, the copyable display
uses the same label and tooltip.
Invalid paths raise ImproperlyConfigured when the ModelAdmin is constructed.
Invalid path syntax and duplicate paths raise ValueError.
RelatedCollectionsOption / RelatedCollectionOption
Added in 1.0.9
Changed in 1.0.10
Changed in 1.0.11
Changed in 1.0.13
Changed in 1.0.14
Changed in 1.0.16
Edits a typed list of values on the parent change form. Chassis renders one
input per related row and provides + and delete controls through Django's
native inline formset. Pass any Django forms.Field subclass through
field_class; it defines the widget, parsing, and validation of every input.
Each collection is a standalone fieldset on the change form and keeps a
vertically centered label aligned with standard Admin fields beside its inputs.
Value controls use a dedicated 45rem column; a green icon-only circle-plus
and red trash actions use a separate, consistently spaced control column and
stay vertically centered against their input without a Django “add another”
row. Every removable row shows a visible trash action. The add action remains
disabled while the last editable row is empty, preventing accidental chains of
blank inputs.
from django import forms
from django.contrib import admin
from django_chassis.mixins import ChassisAdminMixin
from django_chassis.options import RelatedCollectionOption, RelatedCollectionsOption
from project.models import AllowedRedirect, Client
class ClientAdmin(ChassisAdminMixin, admin.ModelAdmin):
options = [
RelatedCollectionsOption(collections=[
RelatedCollectionOption(
model=AllowedRedirect,
foreign_key='client',
value_field='uri',
label='Allowed redirect URIs',
field_class=forms.URLField
)
])
]
To take ownership of persistence, set save_method='save_redirects' on the
collection and implement the named ModelAdmin method:
class ClientAdmin(ChassisAdminMixin, admin.ModelAdmin):
def save_redirects(self, *, request, obj, formset, change):
values = [
data['uri']
for data in formset.cleaned_data
if data and not data.get('DELETE')
]
# Process the validated values for this application.
RelatedCollectionsOption
| Field | Type | Default | Required |
|---|---|---|---|
collections | list[RelatedCollectionOption] | — | yes — definitions must be unique |
RelatedCollectionOption
| Field | Type | Default | Required |
|---|---|---|---|
model | type[Model] | — | yes — dependent model |
foreign_key | str | — | yes — FK on model pointing to the parent model |
value_field | str | — | yes — non-relation field edited by each input |
label | localized string | — | yes — collection fieldset title |
field_class | type[forms.Field] | forms.CharField | no — field type used by every input |
widget_attrs | dict[str, str] | {} | no |
save_method | str | None | None | no — ModelAdmin method receiving the validated formset |
extra | int | 1 | no — initially empty inputs |
min_num | int | 0 | no |
max_num | int | None | None | no |
can_delete | bool | True | no |
Without save_method, the dependent model remains the source of truth and the
native formset saves its rows. With save_method, Chassis calls that ModelAdmin
method with keyword arguments request, obj, formset, and change; the
application can read formset.cleaned_data and perform any required processing.
The custom handler owns persistence and must save the formset itself when that
is desired. Empty extra inputs are ignored. Populated inputs are parsed and
validated by field_class, for example forms.URLField, forms.IntegerField,
or a project-defined field. Invalid relations or handler names raise
ImproperlyConfigured when ModelAdmin is constructed.
RowActionsOption / RowActionOption
Last changelist column. The first column is not a change-link unless
you set chassis_link_first_column = True.
Default without arguments: one view button (Открыть / Open,
fa-solid fa-arrow-right, ButtonColor.PRIMARY, icon display).
from django_chassis.enums import ButtonColor, RowActionDisplay, RowActionType
from django_chassis.options import RowActionOption, RowActionsOption
RowActionsOption(
actions=[
RowActionOption(
action_type=RowActionType.VIEW,
label='Open',
color=ButtonColor.PRIMARY,
icon_class='fa-solid fa-arrow-right',
display=RowActionDisplay.ICON,
),
RowActionOption(
action_type=RowActionType.CHANGE,
label='Edit',
color=ButtonColor.SECONDARY,
icon_class='fa-solid fa-pen',
permission='change',
),
RowActionOption(
action_type=RowActionType.DELETE,
label='Delete',
color=ButtonColor.DANGER,
icon_class='fa-solid fa-trash',
permission='delete',
),
RowActionOption(
action_type=RowActionType.HISTORY,
label='History',
color=ButtonColor.SECONDARY,
icon_class='fa-solid fa-clock-rotate-left',
),
]
)
RowActionsOption
| Field | Type | Default |
|---|---|---|
actions | list[RowActionOption] | one VIEW action |
RowActionOption
| Field | Type | Default | Required |
|---|---|---|---|
action_type | RowActionType | — | yes — view, change, delete, history |
label | localized string | — | yes |
color | ButtonColor | — | yes |
icon_class | Font Awesome class | — | yes |
display | RowActionDisplay | ICON | no — icon or button |
permission | str or None | None | no — inferred from type when possible |
A failed permission hides the button. There is no disabled placeholder.
ListActionsOption / ListActionOption
Toolbar links above the changelist (next to Add and import/export). They resolve a Django URL name; they do not run ModelAdmin methods.
from django_chassis.options import ListActionOption, ListActionsOption
ListActionsOption(
actions=[
ListActionOption(
url_name='admin:catalog_book_changelist',
label='All books',
color=ButtonColor.PRIMARY,
icon_class='fa-solid fa-list',
permission='view',
condition_method='can_show_all_books',
)
]
)
ListActionOption
| Field | Type | Default | Required |
|---|---|---|---|
url_name | Django URL name | — | yes |
label | localized string | — | yes |
color | ButtonColor | PRIMARY | no |
icon_class | Font Awesome class | '' | no |
permission | codename or None | None (treated as view in checks) | no |
condition_method | method name or None | None | no |
condition_method must be a @classmethod shaped (cls, request) -> bool.
False omits the action. A missing or non-classmethod name fails at
ModelAdmin construction (ImproperlyConfigured).
If the permission is missing, the toolbar may show a disabled control (unlike row actions). Import/export buttons are injected here as well when those options are present.
ObjectActionsOption
Names of ModelAdmin methods decorated with @object_action. They appear on
the change form toolbar and get a route:
{admin}/{app}/{model}/{object_id}/actions/{action_name}/
from django_chassis.options import ObjectActionsDropdownOption, ObjectActionsOption
ObjectActionsOption(
actions=['publish'],
dropdown=ObjectActionsDropdownOption(actions=['archive'])
)
| Field | Type | Default |
|---|---|---|
actions | list[str] | [] |
dropdown | ObjectActionsDropdownOption | None | None |
ObjectActionsDropdownOption.actions must be non-empty. Duplicate names within
or across both collections raise ValueError. Six or more visible ungrouped
actions are collapsed automatically.
An undecorated name fails validation at construction.
Decorator parameters are documented on Object actions.
RelatedEntitiesOption / RelatedEntityOption
Independent paginated tables below the fieldsets on the change form
(after_field_sets). Each section calls a @classmethod marked
@chassis_related_items.
from django_chassis.decorators import chassis_related_items
from django_chassis.options import RelatedEntitiesOption, RelatedEntityOption, TableColumnOption, TableOption
RelatedEntitiesOption(
sections=[
RelatedEntityOption(
slug='books',
title='Books',
get_items_method='get_books',
page_size=10,
table=TableOption(
columns=[TableColumnOption(field='title', label='Title'), TableColumnOption(field='isbn', label='ISBN')]
),
)
],
fieldset_title='Related',
collapsed=False,
pagination_state_ttl_seconds=30 * 60,
)
RelatedEntitiesOption
| Field | Type | Default | Required |
|---|---|---|---|
sections | list[RelatedEntityOption] | — | yes |
fieldset_title | localized string | 'Связанные сущности' | no |
collapsed | bool | False | no |
pagination_state_ttl_seconds | int | 1800 | no — must be >= 1 |
RelatedEntityOption
| Field | Type | Default | Required |
|---|---|---|---|
slug | unique section id | — | yes |
title | localized string | — | yes |
get_items_method | method name | — | yes |
table | TableOption | — | yes |
page_size | int | 10 | no — must be >= 1 |
collapsed | bool or None | None (inherit parent) | no |
Provider signature: (cls, request, obj) -> QuerySet | Sequence.
Pagination is per section; page state lives in the query string / session
for pagination_state_ttl_seconds.
TableOption family
Reusable table contract for related entities, information pages, and history-style blocks.
from django_chassis.options import TableActionOption, TableActionUrlKwargOption, TableColumnOption, TableOption
TableOption(
columns=[TableColumnOption(field='title', label='Title'), TableColumnOption(field='status', label='Status')],
fieldset_title='Items',
empty_message='No rows.',
selection_field='id',
selection_disabled_field='locked',
selection_checked_field='selected',
actions=[
TableActionOption(
url_name='admin:catalog_book_change',
label='Open',
icon_class='fa-solid fa-arrow-right',
object_field='id',
object_url_kwarg='object_id',
permission='view',
url_kwargs=[TableActionUrlKwargOption(name='extra', value='kind')],
)
],
)
TableOption
| Field | Type | Default |
|---|---|---|
columns | list[TableColumnOption] | required |
fieldset_title | localized string or None | None |
actions | list[TableActionOption] | [] |
selection_field | row attribute or None | None — checkbox value |
selection_disabled_field | row attribute or None | None — truthy disables |
selection_checked_field | row attribute or None | None — truthy pre-checks |
empty_message | localized string | 'Нет данных для отображения.' |
TableColumnOption
Changed in 1.0.9
| Field | Type | Required |
|---|---|---|
field | dotted path on the row | yes |
label | column header | yes |
help_text | localized string or None | no — shared accessible tooltip |
TableActionOption
| Field | Type | Default |
|---|---|---|
url_name | Django URL name | required |
label | localized string | required |
icon_class | Font Awesome class | required |
color | ButtonColor | PRIMARY |
display | RowActionDisplay | ICON |
object_field | row attribute for the object id | 'id' |
object_url_kwarg | URL kwarg name | 'object_id' |
permission | codename or None | None |
condition_method | method name or None | None |
url_kwargs | extra TableActionUrlKwargOption | [] |
TableActionUrlKwargOption(name, value) adds a constant keyword
argument to reverse(). The object id still comes from object_field
→ object_url_kwarg. If url_name has no :, Chassis prefixes the
current AdminSite name.
permission=None allows the action. A named condition_method that is
missing raises TypeError at render time.
ImportOption
Adds an Import toolbar button and the import routes (upload, preview, apply, history, download).
from django_chassis.enums import ImportFormat
from django_chassis.options import ImportOption
ImportOption(
permission='import_book', fields=['title', 'isbn', 'status'], formats=[ImportFormat.JSON, ImportFormat.XML]
)
| Field | Type | Default | Required |
|---|---|---|---|
permission | non-blank str | — | yes |
fields | list[str] or None | None — all eligible fields | no |
formats | list[ImportFormat] or None | None — every ImportFormat | no |
Validation at construction:
- blank
permission→ValueError formats=[]→ValueError- non-
ImportFormatmembers →TypeError
ImportFormat: JSON, XML.
The permission must exist on the model (or as a PermissionOption).
manage.py check reports chassis.E003 otherwise.
ExportOption
Adds an Export toolbar button and export routes (form, history, download).
from django_chassis.enums import ExportFormat
from django_chassis.options import ExportOption
ExportOption(
permission='export_book',
fields=['title', 'isbn', 'status'],
formats=[ExportFormat.JSON, ExportFormat.CSV, ExportFormat.XLSX],
filter_fields=['status', 'author'],
include_journals=False,
)
| Field | Type | Default | Required |
|---|---|---|---|
permission | non-blank str | — | yes |
fields | list[str] or None | None | no |
formats | list[ExportFormat] or None | None — all enum members | no |
include_journals | bool | False | no — include model history when the project provides it |
filter_fields | list[str] or None | None | no — Django lookups on the export form |
Validation:
- blank
permission→ValueError - empty
formats/filter_fieldslists →ValueError - unknown
filter_fieldslookups →chassis.E004at check time
ExportFormat: JSON, XML, CSV, XLSX.
Files go to STORAGES['media']. See Import and export.
Site-level options
These are not in ModelAdmin.options. They live on
ChassisAdminSiteMixin.
SidebarSectionOption
Collapsible sidebar group.
| Field | Type | Default |
|---|---|---|
slug | str | required |
label | localized string | required |
icon_class | Font Awesome class | required |
items | list[SidebarModelItemOption | SidebarPageItemOption] | required |
icon_color | SidebarIconColor | SLATE |
SidebarModelItemOption
| Field | Type | Default |
|---|---|---|
model | 'app_label.model' | required — must be registered on this site |
label | localized string or None | model verbose name |
icon_class | Font Awesome class | 'fa-solid fa-table-list' |
Hidden when the user lacks model permissions.
SidebarPageItemOption
| Field | Type | Default |
|---|---|---|
page_slug | str | required — page in chassis_page_classes |
label | localized string or None | page label |
icon_class | Font Awesome class | '' |
The page instance must be a PermissionAdminPage. Personal and
superuser pages cannot be sidebar children (ImproperlyConfigured).
SidebarLinkOption
Standalone top-level link (not inside a section).
| Field | Type | Default |
|---|---|---|
slug | str | required |
label | localized string | required |
icon_class | Font Awesome class | required |
url_name | Django URL name | required |
icon_color | SidebarIconColor or None | None |
icon_color applies the sidebar icon palette to a standalone link while
keeping the link outside a collapsible section.
Duplicate slugs and unknown model/page references fail site checks.
AdminPageGroupOption
Groups custom pages into a navbar dropdown and/or a dashboard actions
section. Reused as AdminPage.navbar_group and AdminPage.dashboard_group.
| Field | Type | Default |
|---|---|---|
slug | str | required |
label | localized string | required |
icon_class | Font Awesome class | required |
order | int | 0 |
PersonalAdminPage cannot join a group.
PermissionOption
Declares a permission that Chassis registers and creates after migrate.
from django_chassis.options import PermissionOption
PermissionOption(app_label='catalog', model='book', codename='export_book', name='Can export book')
| Field | Type | Constraint |
|---|---|---|
app_label | str | Python identifier |
model | str | lowercase identifier |
codename | str | identifier |
name | localized string | non-empty |
value property: '{app_label}.{codename}'.
Assign on the site as chassis_permission_options = (export_books,).
PermissionAdminPage.permission must be a view_* PermissionOption.
Construction and checks
| Failure | When | What |
|---|---|---|
ValueError / TypeError | option __post_init__ | blank import/export permission, empty lists, duplicate action names, non-positive page size |
ImproperlyConfigured | ModelAdmin / site __init__ | missing condition classmethods, bad decimal fields, invalid page access contracts |
chassis.E002 | manage.py check | Django @admin.action without allowed_permissions |
chassis.E003 | manage.py check | action / import / export permission not declared on the model |
chassis.E004 | manage.py check | unknown ExportOption.filter_fields lookup |
See also
- ModelAdmin — MRO,
optionslist, companion mixins - Changelist — how the list page is assembled
- API reference — compact signatures