Перейти к основному содержимому

Каталог options

Добавлено в 1.0.1

Каждая возможность Chassis — frozen dataclass. Не нужно наследовать отдельный mixin для поиска, badges и export. Option-объекты кладутся в ModelAdmin.options или назначаются на ChassisAdminSiteMixin.

Эта страница — полный каталог: зачем option, поля, значения по умолчанию, валидация и какой регион UI он управляет.

Как работает lookup

ChassisAdminMixin.get_chassis_option(option_class=...) возвращает первый экземпляр этого типа в локальном списке options. Если в локальном списке нет совпадения, берётся значение из ChassisAdminMixin.options[RowActionsOption()].

Следствия:

  • Используется не больше одного экземпляра каждого типа. Несколько групп FK-вкладок кладите внутрь одного ForeignKeyTabsOption, а не тремя соседними option.
  • Если задать options = [SearchOption(...)] и не указать RowActionsOption, mixin всё равно подставит кнопку просмотра из class-level списка.
  • Чтобы скрыть row actions, передайте RowActionsOption(actions=[]).
  • Settingsне AdminOption. Его назначают в chassis_settings.

Атрибут options переименовывать нельзя.

Объединение AdminOption

Эти типы допустимы в ModelAdmin.options:

OptionРегион страницы
SearchOptionFieldset поиска changelist
FiltersOptionFieldset фильтров changelist
DateHierarchyOptionИерархия дат changelist
FieldTabsOptionВкладки по choices
ForeignKeyTabsOptionВкладки по ForeignKey
BadgeFieldsOptionBadge-колонки changelist
PrettyJsonOptionJSON на change form / списке
DecimalAmountOptionЦелая сумма как Decimal
RowActionsOptionПоследняя колонка changelist
ListActionsOptionТулбар changelist
ObjectActionsOptionТулбар change form
RelatedEntitiesOptionСвязанные таблицы change form
ImportOptionФлоу импорта и кнопка тулбара
ExportOptionФлоу экспорта и кнопка тулбара

Вложенные типы (RowActionOption, TableColumnOption, …) не входят в AdminOption. Они живут внутри родительского option.

Site-level типы (Sidebar*, AdminPageGroupOption, PermissionOption) назначаются на AdminSite, не в options.


Settings

Не option. Назначается в chassis_settings у ModelAdmin или AdminPage.

from django_chassis.options import Settings

chassis_settings = Settings(
search_collapsed=True, date_hierarchy_collapsed=True, filters_collapsed=True, allow_standard_add=True
)
ПолеТипПо умолчаниюЭффект
search_collapsedboolTrueПоиск изначально свёрнут
date_hierarchy_collapsedboolTrueИерархия дат изначально свёрнута
filters_collapsedboolTrueФильтры изначально свёрнуты
allow_standard_addboolTrueКнопка «Добавить» Django в тулбаре changelist

allow_standard_add=False заставляет has_add_permission() вернуть False, поэтому стандартная кнопка «Добавить» исчезает. List actions и кнопки import/export не затрагиваются.


SearchOption

Выносит Django search_fields в fieldset Chassis над таблицей. Mixin записывает search_fields в instance, чтобы checks Django их видели.

from django_chassis.options import SearchOption

SearchOption(fields=['title', 'isbn', 'author__name'], fieldset_title='Поиск', placeholder='Название, ISBN или автор')
ПолеТипПо умолчаниюОбязательно
fieldslist[str]да
fieldset_titlestr или gettext lazy_('Поиск')нет
placeholderstr или gettext lazy''нет

fields использует lookup Django (icontains по умолчанию, префикс ^, точное =, полнотекст @ — как в стандартном Admin).

Без этой option у changelist нет fieldset поиска.


FiltersOption

Рисует select-фильтры Chassis в отдельном fieldset. fields становится Django list_filter.

from django.contrib.admin import SimpleListFilter
from django_chassis.options import FiltersOption

FiltersOption(fields=['status', 'author', PublishedThisYearFilter], fieldset_title='Фильтры')
ПолеТипПо умолчаниюОбязательно
fieldslist[Any]да
fieldset_titleлокализованная строка_('Фильтры')нет

Допустимы те же значения, что у Django list_filter: имена полей, related lookup и подклассы SimpleListFilter.

Правый sidebar фильтров Django подавлен ({% block filters %}{% endblock %}). Фильтры живут в стеке контролов Chassis над таблицей.


DateHierarchyOption

Включает Django date_hierarchy и оборачивает его в fieldset Chassis.

from django_chassis.options import DateHierarchyOption

DateHierarchyOption(field='published_at', fieldset_title='Даты')
ПолеТипПо умолчаниюОбязательно
fieldstrда — имя DateField / DateTimeField
fieldset_titleлокализованная строка_('Даты')нет

Mixin записывает date_hierarchy на instance для checks Django.


FieldTabsOption

Вкладки (или <select>), которые фильтруют changelist по полю choices текущей модели. Каждая вкладка — ссылка с query-string; «Все» сбрасывает фильтр.

from django_chassis.enums import TabDisplay
from django_chassis.options import FieldTabsOption

FieldTabsOption(
field='status', choices=Book.Status.choices, display=TabDisplay.BUTTONS, all_label='Все', fieldset_title='Статус'
)
ПолеТипПо умолчаниюОбязательно
fieldstrда
choiceslist[tuple[Any, Any]]да — пары (value, label)
displayTabDisplayTabDisplay.BUTTONSнет
all_labelлокализованная строка_('Все')нет
fieldset_titleлокализованная строка_('Tabs')нет

TabDisplay.BUTTONS — ряд ссылок. TabDisplay.SELECT — выпадающий список с переходом при смене значения.

Для локального choices-поля — эта option. Для связанной модели — ForeignKeyTabsOption.


ForeignKeyTabsOption

Одна или несколько групп вкладок, каждая привязана к ForeignKey текущей модели. Каждый связанный объект из queryset становится вкладкой.

from django_chassis.options import ForeignKeyTabGroupOption, ForeignKeyTabsOption

ForeignKeyTabsOption(
groups=[
ForeignKeyTabGroupOption(field='author', model=Author, label='Авторы', all_label='Все авторы'),
ForeignKeyTabGroupOption(field='publisher', model=Publisher, label='Издатели'),
],
display=TabDisplay.BUTTONS,
fieldset_title='Связи',
)

Короткий синтаксис одной группы

ForeignKeyTabsOption(field='author', model=Author)

эквивалентен одному ForeignKeyTabGroupOption в groups.

ПолеТипПо умолчаниюОбязательно
groupslist[ForeignKeyTabGroupOption][]либо groups, либо field+model
fieldstr или NoneNoneshortcut
modelкласс модели или NoneNoneshortcut
displayTabDisplayBUTTONSнет
all_labelлокализованная строка_('Все')нет
fieldset_titleлокализованная строка_('Tabs')нет

ForeignKeyTabGroupOption

ПолеТипПо умолчаниюОбязательно
fieldимя FK на текущей моделида
modelкласс связанной моделида
labelлокализованная строка''нет — заголовок группы
all_labelлокализованная строка_('Все')нет

Два объекта ForeignKeyTabsOption повесить нельзя. Все группы — в groups.


BadgeFieldsOption

Показывает названные колонки changelist цветными badge. Mixin подменяет каждое перечисленное поле в list_display сгенерированным display-методом.

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}},
)
ПолеТипПо умолчаниюОбязательно
fieldslist[str]да
colorsMapping[str, Mapping[object, ButtonColor]]{}нет

Без маппинга цвета используется тон badge по умолчанию. Ключи внутреннего маппинга — сырые значения поля (члены enum, строки, bool).

ButtonColor: primary, secondary, success, warning, danger, info.


PrettyJsonOption

Для каждого JSON-поля создаёт read-only метод pretty_<field> и подсвечивает значение через Pygments. Доменный ModelAdmin эти методы не объявляет.

from django_chassis.options import PrettyJsonOption

PrettyJsonOption(fields=['payload', 'metadata'])
ПолеТипПо умолчаниюОбязательно
fieldslist[str]да

Исходное имя поля укажите в list_display / readonly_fields, если нужна pretty-колонка. Mixin ставит метод в __init__.


DecimalAmountOption

Показывает целочисленные суммы в минимальных единицах как Decimal. На модели должны быть методы:

  • _get_fraction_number(...)
  • convert_amount_to_decimal(...)

Если любого метода нет, option молча игнорируется (колонки не переписываются). Если имя не IntegerField, при создании — ImproperlyConfigured.

from django_chassis.options import DecimalAmountOption

DecimalAmountOption(fields=['amount', 'fee'])
ПолеТипПо умолчаниюОбязательно
fieldslist[str]да — уникальные имена IntegerField

Повтор имён: ValueError('Chassis decimal amount field names must be unique.').

Сгенерированное имя в list-display: chassis_decimal_<field>. Сортировка идёт по исходному integer.


RowActionsOption / RowActionOption

Последняя колонка changelist. Первая колонка не ссылка на change, пока не задано chassis_link_first_column = True.

По умолчанию без аргументов: одна кнопка просмотра (Открыть, fa-solid fa-arrow-right, ButtonColor.PRIMARY, отображение иконкой).

from django_chassis.enums import ButtonColor, RowActionDisplay, RowActionType
from django_chassis.options import RowActionOption, RowActionsOption

RowActionsOption(
actions=[
RowActionOption(
action_type=RowActionType.VIEW,
label='Открыть',
color=ButtonColor.PRIMARY,
icon_class='fa-solid fa-arrow-right',
display=RowActionDisplay.ICON,
),
RowActionOption(
action_type=RowActionType.CHANGE,
label='Изменить',
color=ButtonColor.SECONDARY,
icon_class='fa-solid fa-pen',
permission='change',
),
RowActionOption(
action_type=RowActionType.DELETE,
label='Удалить',
color=ButtonColor.DANGER,
icon_class='fa-solid fa-trash',
permission='delete',
),
RowActionOption(
action_type=RowActionType.HISTORY,
label='История',
color=ButtonColor.SECONDARY,
icon_class='fa-solid fa-clock-rotate-left',
),
]
)

RowActionsOption

ПолеТипПо умолчанию
actionslist[RowActionOption]одно действие VIEW

RowActionOption

ПолеТипПо умолчаниюОбязательно
action_typeRowActionTypeда — view, change, delete, history
labelлокализованная строкада
colorButtonColorда
icon_classкласс Font Awesomeда
displayRowActionDisplayICONнет — icon или button
permissionstr или NoneNoneнет — при возможности выводится из типа

Нет права — кнопка скрыта. Disabled-заглушки нет.


ListActionsOption / ListActionOption

Ссылки тулбара над changelist (рядом с «Добавить» и import/export). Резолвят имя URL Django; методы ModelAdmin не вызывают.

from django_chassis.options import ListActionOption, ListActionsOption

ListActionsOption(
actions=[
ListActionOption(
url_name='admin:catalog_book_changelist',
label='Все книги',
color=ButtonColor.PRIMARY,
icon_class='fa-solid fa-list',
permission='view',
condition_method='can_show_all_books',
)
]
)

ListActionOption

ПолеТипПо умолчаниюОбязательно
url_nameимя URL Djangoда
labelлокализованная строкада
colorButtonColorPRIMARYнет
icon_classкласс Font Awesome''нет
permissioncodename или NoneNone (в checks как view)нет
condition_methodимя метода или NoneNoneнет

condition_method@classmethod вида (cls, request) -> bool. False убирает действие. Отсутствующее имя или не-classmethod — ImproperlyConfigured при создании ModelAdmin.

Если права нет, в тулбаре может быть disabled-контрол (в отличие от row actions). Кнопки import/export тоже попадают сюда.


ObjectActionsOption

Имена методов ModelAdmin с декоратором @object_action. Они появляются в тулбаре change form и получают маршрут:

{admin}/{app}/{model}/{object_id}/actions/{action_name}/

from django_chassis.options import ObjectActionsOption

ObjectActionsOption(actions=['publish', 'archive'])
ПолеТипПо умолчанию
actionslist[str][]

Повтор имён: ValueError('Chassis object action names must be unique.'). Имя без декоратора падает на валидации при создании.

Параметры декоратора — на странице Объектные действия.


RelatedEntitiesOption / RelatedEntityOption

Независимые таблицы с пагинацией под fieldsets change form (after_field_sets). Каждая секция вызывает @classmethod с @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='Книги',
get_items_method='get_books',
page_size=10,
table=TableOption(
columns=[
TableColumnOption(field='title', label='Название'),
TableColumnOption(field='isbn', label='ISBN'),
]
),
)
],
fieldset_title='Связанные',
collapsed=False,
pagination_state_ttl_seconds=30 * 60,
)

RelatedEntitiesOption

ПолеТипПо умолчаниюОбязательно
sectionslist[RelatedEntityOption]да
fieldset_titleлокализованная строка'Связанные сущности'нет
collapsedboolFalseнет
pagination_state_ttl_secondsint1800нет — должно быть >= 1

RelatedEntityOption

ПолеТипПо умолчаниюОбязательно
slugуникальный id секциида
titleлокализованная строкада
get_items_methodимя методада
tableTableOptionда
page_sizeint10нет — должно быть >= 1
collapsedbool или NoneNone (наследует родителя)нет

Сигнатура провайдера: (cls, request, obj) -> QuerySet | Sequence. Пагинация независима; состояние страницы живёт в query string / session pagination_state_ttl_seconds секунд.


Семейство TableOption

Общий контракт таблицы для связанных сущностей, информационных страниц и блоков истории.

from django_chassis.options import TableActionOption, TableActionUrlKwargOption, TableColumnOption, TableOption

TableOption(
columns=[TableColumnOption(field='title', label='Название'), TableColumnOption(field='status', label='Статус')],
fieldset_title='Элементы',
empty_message='Нет строк.',
selection_field='id',
selection_disabled_field='locked',
selection_checked_field='selected',
actions=[
TableActionOption(
url_name='admin:catalog_book_change',
label='Открыть',
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

ПолеТипПо умолчанию
columnslist[TableColumnOption]обязательно
fieldset_titleлокализованная строка или NoneNone
actionslist[TableActionOption][]
selection_fieldатрибут строки или NoneNone — значение checkbox
selection_disabled_fieldатрибут строки или NoneNone — truthy отключает
selection_checked_fieldатрибут строки или NoneNone — truthy отмечает заранее
empty_messageлокализованная строка'Нет данных для отображения.'

TableColumnOption

ПолеТипОбязательно
fielddotted-путь на объекте строкида
labelзаголовок колонкида

TableActionOption

ПолеТипПо умолчанию
url_nameимя URL Djangoобязательно
labelлокализованная строкаобязательно
icon_classкласс Font Awesomeобязательно
colorButtonColorPRIMARY
displayRowActionDisplayICON
object_fieldатрибут строки для id объекта'id'
object_url_kwargимя URL kwarg'object_id'
permissioncodename или NoneNone
condition_methodимя метода или NoneNone
url_kwargsдополнительные TableActionUrlKwargOption[]

TableActionUrlKwargOption(name, value) добавляет постоянный именованный аргумент в reverse(). Id объекта по-прежнему берётся из object_fieldobject_url_kwarg. Если в url_name нет :, Chassis добавляет имя текущего AdminSite.

permission=None разрешает действие. Отсутствующий condition_method даёт TypeError в момент рендера.


ImportOption

Добавляет кнопку Import в тулбар и маршруты импорта (загрузка, preview, apply, история, скачивание).

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]
)
ПолеТипПо умолчаниюОбязательно
permissionнепустая strда
fieldslist[str] или NoneNone — все подходящие полянет
formatslist[ImportFormat] или NoneNone — все ImportFormatнет

Валидация при создании:

  • пустой permissionValueError
  • formats=[]ValueError
  • элементы не из ImportFormatTypeError

ImportFormat: JSON, XML.

Право должно существовать на модели (или как PermissionOption). Иначе manage.py check сообщает chassis.E003.


ExportOption

Добавляет кнопку Export в тулбар и маршруты экспорта (форма, история, скачивание).

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,
)
ПолеТипПо умолчаниюОбязательно
permissionнепустая strда
fieldslist[str] или NoneNoneнет
formatslist[ExportFormat] или NoneNone — все члены enumнет
include_journalsboolFalseнет — история модели, если проект её даёт
filter_fieldslist[str] или NoneNoneнет — lookup Django на форме экспорта

Валидация:

  • пустой permissionValueError
  • пустые списки formats / filter_fieldsValueError
  • неизвестные lookup в filter_fieldschassis.E004 на check

ExportFormat: JSON, XML, CSV, XLSX.

Файлы пишутся в STORAGES['media']. См. Import и export.


Site-level options

Эти типы не входят в ModelAdmin.options. Они живут на ChassisAdminSiteMixin.

SidebarSectionOption

Раскрываемый раздел sidebar.

ПолеТипПо умолчанию
slugstrобязательно
labelлокализованная строкаобязательно
icon_classкласс Font Awesomeобязательно
itemslist[SidebarModelItemOption | SidebarPageItemOption]обязательно
icon_colorSidebarIconColorSLATE

SidebarModelItemOption

ПолеТипПо умолчанию
model'app_label.model'обязательно — модель зарегистрирована на этом site
labelлокализованная строка или Noneverbose name модели
icon_classкласс Font Awesome'fa-solid fa-table-list'

Скрыт, если у пользователя нет прав на модель.

SidebarPageItemOption

ПолеТипПо умолчанию
page_slugstrобязательно — страница в chassis_page_classes
labelлокализованная строка или Nonelabel страницы
icon_classкласс Font Awesome''

Экземпляр страницы должен быть PermissionAdminPage. Personal и superuser страницы нельзя класть в sidebar (ImproperlyConfigured).

SidebarLinkOption

Самостоятельная ссылка верхнего уровня (не внутри раздела).

ПолеТипПо умолчанию
slugstrобязательно
labelлокализованная строкаобязательно
icon_classкласс Font Awesomeобязательно
url_nameимя URL Djangoобязательно

Повтор slug и неизвестные model/page ссылки падают на checks сайта.

AdminPageGroupOption

Группирует кастомные страницы в dropdown navbar и/или секцию действий dashboard. Тот же тип — AdminPage.navbar_group и AdminPage.dashboard_group.

ПолеТипПо умолчанию
slugstrобязательно
labelлокализованная строкаобязательно
icon_classкласс Font Awesomeобязательно
orderint0

PersonalAdminPage в группу входить не может.

PermissionOption

Описывает право, которое Chassis регистрирует и создаёт после migrate.

from django_chassis.options import PermissionOption

PermissionOption(app_label='catalog', model='book', codename='export_book', name='Может экспортировать книгу')
ПолеТипОграничение
app_labelstrидентификатор Python
modelstrидентификатор в нижнем регистре
codenamestrидентификатор
nameлокализованная строканепустая

Свойство value: '{app_label}.{codename}'.

На сайте: chassis_permission_options = (export_books,). PermissionAdminPage.permission должен быть PermissionOption с view_*.


Создание и checks

ОшибкаКогдаЧто
ValueError / TypeError__post_init__ optionпустой permission import/export, пустые списки, повтор имён действий, неположительный page size
ImproperlyConfigured__init__ ModelAdmin / siteнет classmethod условия, плохие decimal-поля, неверный контракт доступа страницы
chassis.E002manage.py checkDjango @admin.action без allowed_permissions
chassis.E003manage.py checkpermission действия / import / export не объявлен на модели
chassis.E004manage.py checkнеизвестный lookup в ExportOption.filter_fields

См. также

  • ModelAdmin — MRO, список options, сопутствующие миксины
  • Changelist — как собирается страница списка
  • Справочник API — компактные сигнатуры