Skip to main content

Options catalog

Added in 1.0.1

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 omit RowActionsOption, the mixin still injects the default view button from the class-level list.
  • To hide row actions, pass RowActionsOption(actions=[]).
  • Settings is not an AdminOption. Assign it to chassis_settings.

Do not rename the options attribute.

AdminOption union​

These types are legal on ModelAdmin.options:

OptionPage region
SearchOptionChangelist search fieldset
FiltersOptionChangelist filter fieldset
DateHierarchyOptionChangelist date drill-down
FieldTabsOptionChangelist choice tabs
ForeignKeyTabsOptionChangelist FK tabs
BadgeFieldsOptionChangelist badge columns
CopyableFieldsOptionRead-only values with copy buttons
PrettyJsonOptionChange form / list JSON
DecimalAmountOptionInteger money as Decimal
RelatedFieldsOptionRead-only values from related model paths
RelatedCollectionsOptionEditable values stored in a dependent model
RowActionsOptionLast changelist column
ListActionsOptionChangelist toolbar
ObjectActionsOptionChange-form toolbar
RelatedEntitiesOptionChange-form related tables
ImportOptionImport flow + toolbar button
ExportOptionExport 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
)
FieldTypeDefaultEffect
search_collapsedboolTrueSearch fieldset starts collapsed
date_hierarchy_collapsedboolTrueDate hierarchy starts collapsed
filters_collapsedboolTrueFilters fieldset starts collapsed
allow_standard_addboolTrueShow 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')
FieldTypeDefaultRequired
fieldslist[str]—yes
fieldset_titlestr or gettext lazy_('Поиск')no
placeholderstr 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')
FieldTypeDefaultRequired
fieldslist[Any]—yes
fieldset_titlelocalized 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')
FieldTypeDefaultRequired
fieldstr—yes — DateField / DateTimeField name
fieldset_titlelocalized 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'
)
FieldTypeDefaultRequired
fieldstr—yes
choiceslist[tuple[Any, Any]]—yes — (value, label) pairs
displayTabDisplayTabDisplay.BUTTONSno
all_labellocalized string_('Все')no
fieldset_titlelocalized 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.

FieldTypeDefaultRequired
groupslist[ForeignKeyTabGroupOption][]one of groups or field+model
fieldstr or NoneNoneshortcut
modelmodel class or NoneNoneshortcut
displayTabDisplayBUTTONSno
all_labellocalized string_('Все')no
fieldset_titlelocalized string_('Tabs')no
queryset_filtersdict[str, object]{}no — shortcut choice filter

ForeignKeyTabGroupOption​

FieldTypeDefaultRequired
fieldFK field name on the current model—yes
modelrelated model class—yes
labellocalized string''no — group heading
all_labellocalized string_('Все')no
queryset_filtersdict[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}},
)
FieldTypeDefaultRequired
fieldslist[str]—yes
colorsMapping[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']
)
FieldTypeDefaultRequired
fieldslist[str]—yes — unique names
editable_on_addboolFalseno — preserve the source input while creating an object
masked_fieldslist[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'])
FieldTypeDefaultRequired
fieldslist[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(...)
Changed in 1.0.7

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'])
FieldTypeDefaultRequired
fieldslist[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​

FieldTypeDefaultRequired
fieldslist[RelatedFieldOption]—yes — unique paths

RelatedFieldOption​

FieldTypeDefaultRequired
fieldstr—yes — valid __ relation path or model attribute
labelstr | Promise—yes; pass _('…') for localization
help_textstr | Promise | NoneNoneno
empty_value_displaystr | Promise | NoneNoneno — 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​

FieldTypeDefaultRequired
collectionslist[RelatedCollectionOption]—yes — definitions must be unique

RelatedCollectionOption​

FieldTypeDefaultRequired
modeltype[Model]—yes — dependent model
foreign_keystr—yes — FK on model pointing to the parent model
value_fieldstr—yes — non-relation field edited by each input
labellocalized string—yes — collection fieldset title
field_classtype[forms.Field]forms.CharFieldno — field type used by every input
widget_attrsdict[str, str]{}no
save_methodstr | NoneNoneno — ModelAdmin method receiving the validated formset
extraint1no — initially empty inputs
min_numint0no
max_numint | NoneNoneno
can_deleteboolTrueno

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​

FieldTypeDefault
actionslist[RowActionOption]one VIEW action

RowActionOption​

FieldTypeDefaultRequired
action_typeRowActionType—yes — view, change, delete, history
labellocalized string—yes
colorButtonColor—yes
icon_classFont Awesome class—yes
displayRowActionDisplayICONno — icon or button
permissionstr or NoneNoneno — 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​

FieldTypeDefaultRequired
url_nameDjango URL name—yes
labellocalized string—yes
colorButtonColorPRIMARYno
icon_classFont Awesome class''no
permissioncodename or NoneNone (treated as view in checks)no
condition_methodmethod name or NoneNoneno

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'])
)
FieldTypeDefault
actionslist[str][]
dropdownObjectActionsDropdownOption | NoneNone

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​

FieldTypeDefaultRequired
sectionslist[RelatedEntityOption]—yes
fieldset_titlelocalized string'Связанные сущности'no
collapsedboolFalseno
pagination_state_ttl_secondsint1800no — must be >= 1

RelatedEntityOption​

FieldTypeDefaultRequired
slugunique section id—yes
titlelocalized string—yes
get_items_methodmethod name—yes
tableTableOption—yes
page_sizeint10no — must be >= 1
collapsedbool or NoneNone (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​

FieldTypeDefault
columnslist[TableColumnOption]required
fieldset_titlelocalized string or NoneNone
actionslist[TableActionOption][]
selection_fieldrow attribute or NoneNone — checkbox value
selection_disabled_fieldrow attribute or NoneNone — truthy disables
selection_checked_fieldrow attribute or NoneNone — truthy pre-checks
empty_messagelocalized string'Нет данных для отображения.'

TableColumnOption​

Changed in 1.0.9
FieldTypeRequired
fielddotted path on the rowyes
labelcolumn headeryes
help_textlocalized string or Noneno — shared accessible tooltip

TableActionOption​

FieldTypeDefault
url_nameDjango URL namerequired
labellocalized stringrequired
icon_classFont Awesome classrequired
colorButtonColorPRIMARY
displayRowActionDisplayICON
object_fieldrow attribute for the object id'id'
object_url_kwargURL kwarg name'object_id'
permissioncodename or NoneNone
condition_methodmethod name or NoneNone
url_kwargsextra 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]
)
FieldTypeDefaultRequired
permissionnon-blank str—yes
fieldslist[str] or NoneNone — all eligible fieldsno
formatslist[ImportFormat] or NoneNone — every ImportFormatno

Validation at construction:

  • blank permission → ValueError
  • formats=[] → ValueError
  • non-ImportFormat members → 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,
)
FieldTypeDefaultRequired
permissionnon-blank str—yes
fieldslist[str] or NoneNoneno
formatslist[ExportFormat] or NoneNone — all enum membersno
include_journalsboolFalseno — include model history when the project provides it
filter_fieldslist[str] or NoneNoneno — Django lookups on the export form

Validation:

  • blank permission → ValueError
  • empty formats / filter_fields lists → ValueError
  • unknown filter_fields lookups → chassis.E004 at 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.

FieldTypeDefault
slugstrrequired
labellocalized stringrequired
icon_classFont Awesome classrequired
itemslist[SidebarModelItemOption | SidebarPageItemOption]required
icon_colorSidebarIconColorSLATE

SidebarModelItemOption​

FieldTypeDefault
model'app_label.model'required — must be registered on this site
labellocalized string or Nonemodel verbose name
icon_classFont Awesome class'fa-solid fa-table-list'

Hidden when the user lacks model permissions.

SidebarPageItemOption​

FieldTypeDefault
page_slugstrrequired — page in chassis_page_classes
labellocalized string or Nonepage label
icon_classFont 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).

FieldTypeDefault
slugstrrequired
labellocalized stringrequired
icon_classFont Awesome classrequired
url_nameDjango URL namerequired
icon_colorSidebarIconColor or NoneNone
Added in 1.0.6

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.

FieldTypeDefault
slugstrrequired
labellocalized stringrequired
icon_classFont Awesome classrequired
orderint0

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')
FieldTypeConstraint
app_labelstrPython identifier
modelstrlowercase identifier
codenamestridentifier
namelocalized stringnon-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​

FailureWhenWhat
ValueError / TypeErroroption __post_init__blank import/export permission, empty lists, duplicate action names, non-positive page size
ImproperlyConfiguredModelAdmin / site __init__missing condition classmethods, bad decimal fields, invalid page access contracts
chassis.E002manage.py checkDjango @admin.action without allowed_permissions
chassis.E003manage.py checkaction / import / export permission not declared on the model
chassis.E004manage.py checkunknown ExportOption.filter_fields lookup

See also​