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

Свои страницы

Добавлено в 1.0.1

Кастомные страницы живут на AdminSite. Они используют оболочку Chassis (sidebar, navbar, бренд, breadcrumbs), но это не ModelAdmin. Каждый класс обязан объявить ровно один контракт доступа.

КлассДоступГруппы
PermissionAdminPagePermissionOption с codename view_*можно в navbar / dashboard
PersonalAdminPageаутентифицированный staffнельзя в группы
SuperuserAdminPageактивный superuserможно в группы

Все они наследуют AdminPage. При создании сайта — ImproperlyConfigured, если класс смешивает два контракта, не объявляет ни одного или кладёт personal-страницу в группу.

from django.http import HttpRequest, HttpResponse
from django.utils.translation import gettext_lazy as _

from django_chassis.options import AdminPageGroupOption, PermissionOption
from django_chassis.views import PermissionAdminPage

reports_group = AdminPageGroupOption(slug='reports', label=_('Отчёты'), icon_class='fa-solid fa-chart-line', order=10)

view_inventory = PermissionOption(
app_label='catalog', model='book', codename='view_inventory', name=_('Может смотреть склад')
)


class InventoryPage(PermissionAdminPage):
slug = 'inventory'
title = _('Склад')
label = _('Склад')
description = _('Обзор остатков')
icon_class = 'fa-solid fa-boxes-stacked'
permission = view_inventory
navbar_group = reports_group
dashboard_group = reports_group

def view(self, request: HttpRequest) -> HttpResponse:
return self.render(request, rows=[])

Класс регистрируется на сайте:

class CustomAdminSite(ChassisAdminSiteMixin, AdminSite):
chassis_page_classes = (InventoryPage,)

AdminPageService монтирует маршруты. Чтобы PermissionAdminPage была в sidebar, добавьте SidebarPageItemOption(page_slug='inventory') в sidebar_items. Personal и superuser страницы нельзя класть в sidebar как дочерние пункты.

Анатомия страницы​

Шаблон по умолчанию: admin/chassis/page.html.

┌─ breadcrumbs ─────────────────────────────────────────────┐
│ Dashboard › раздел sidebar › label страницы │
├─ тулбар (`page_actions`) ─────────────────────────────────┤
│ опциональные кнопки (информационные страницы) │
├─ title / description ─────────────────────────────────────┤
├─ `chassis_page_content` ──────────────────────────────────┤
│ то, что `view()` / `render()` положили в контекст │
└───────────────────────────────────────────────────────────┘
Изменено в 1.0.7

Общая оболочка страницы использует всю ширину контента и выводит ошибки формы form через единый danger alert. Используйте chassis-page-actions для общей нижней панели с выравниванием вправо и admin/chassis/back_button.html для возврата. Общий шаблон form_rows.html помечает обязательные поля и переносит обязательные checkbox подтверждения после остальных контролов.

dispatch() проверяет has_view_permission. Отказ — PermissionDenied (страница ошибки Chassis, если подключён AdminErrorPageMiddleware). Успех вызывает view().

render(request, **context) смешивает:

  • admin_site.each_context(request) (бренд, sidebar, navbar, footer)
  • chassis_page — экземпляр страницы
  • title / sidebar_section_label из AdminSidebarService
  • любые дополнительные kwargs

Атрибуты AdminPage​

АтрибутТипПо умолчаниюНазначение
slugstrобязательносегмент URL и ссылка sidebar
titleлокализованная строкаобязательнозаголовок
labelлокализованная строкаобязательноподпись в навигации
descriptionлокализованная строка''необязательный лид
icon_classкласс Font Awesome'fa-solid fa-table-list'sidebar / группы
orderint0порядок среди страниц
template_namestr'admin/chassis/page.html'можно переопределить
filters_fieldset_titleлокализованная строка_('Фильтры')если страница рисует фильтры
chassis_settingsSettingsSettings()те же флаги свёртки, что у ModelAdmin
navbar_groupAdminPageGroupOption или NoneNonedropdown navbar
dashboard_groupAdminPageGroupOption или NoneNoneсекция действий dashboard
route_prefixstr'pages'первый сегмент URL

URL: {admin}/{route_prefix}/{slug}/. Имя URL: chassis_page_{slug} (в namespace AdminSite).

Реализуйте view(self, request) (не get() / post() на базе — dispatch всегда вызывает view). Ветку POST делайте внутри view по request.method.

Контракты доступа​

PermissionAdminPage​

permission должен быть PermissionOption с codename, который начинается с view_. Сайт регистрирует его сам. Проверка идёт через AdminPermissionService / has_request_user_permission (по умолчанию group-only).

PersonalAdminPage​

Любой аутентифицированный staff. Нельзя задавать navbar_group и dashboard_group. Для «мой профиль», «мои токены» и похожих экранов.

SuperuserAdminPage​

request.user.is_active и is_superuser.

Страницы объекта​

AdminObjectPage[T] расширяет кастомную страницу списком, карточкой объекта и методами @object_action. Объект не обязан быть моделью Django: вы сами его резолвите.

Дополнительные маршруты:

МаршрутИмя
{prefix}/{slug}/chassis_page_{slug} — список (view)
{prefix}/{slug}/{object_id}/chassis_page_{slug}_object
{prefix}/{slug}/{object_id}/actions/{action_name}/chassis_page_{slug}_object_action

Нужно реализовать:

МетодРоль
view(request)страница списка
get_object(request, object_id) -> T | NoneNone → HTTP 404
get_object_context_data(request, object_id, obj)доп. контекст карточки
object_actionsсписок имён методов @object_action

Шаблон карточки: admin/chassis/object_page.html (object_template_name). В тулбаре — разрешённые объектные действия. Permission и condition / condition_method проверяются повторно на URL действия.

Если объект исчез, действие редиректит на список с ошибкой. Неизвестное или запрещённое действие возвращает на карточку.

Информационные страницы​

AdminInformationPage — структурированный отчёт (секции, алерты, действия шапки, timeline). См. Информационные страницы.

См. также​

Страницы мастера​

Добавлено в 1.0.22

WizardAdminPage добавляет навигацию по этапам к штатной оболочке страницы. Объедините его ровно с одним контрактом доступа (PermissionAdminPage, PersonalAdminPage или SuperuserAdminPage) и зарегистрируйте итоговый класс в chassis_page_classes.

from django.http import HttpRequest, HttpResponse
from django_chassis.dto import WizardStepDTO
from django_chassis.views import SuperuserAdminPage, WizardAdminPage


class SetupPage(WizardAdminPage, SuperuserAdminPage):
slug = 'setup'
title = 'Настройка'
label = 'Настройка'

def view(self, request: HttpRequest) -> HttpResponse:
return self.render(
request=request,
wizard_steps=[
WizardStepDTO(label='Настройки', url=self.get_url(), state='current', available=True, selected=True),
WizardStepDTO(label='Проверка', url='', state='locked', available=False)
]
)

Шаблон проекта наследует admin/chassis/wizard_page.html и заполняет блок chassis_wizard_content формой или результатом этапа. Штатный шаблон подключает стили компонента и admin/chassis/wizard_steps.html.

Неизменяемый WizardStepDTO содержит label, url, state, available и selected=False. Состояния: complete, error, current, ready, locked. Требуется хотя бы один этап и ровно один выбранный доступный этап; неверная конфигурация вызывает ImproperlyConfigured. Подписи и URL экранируются. Доступные этапы являются ссылками; у закрытых этапов ссылки нет и задан aria-disabled="true". Выбранная ссылка получает aria-current="step".

Chassis отображает прогресс. Проект отвечает за хранение, валидацию, транзакции, идемпотентность и права каждого GET/POST и действия. Закрытая ссылка не заменяет серверную проверку перехода. Компонент не добавляет хранение в сессии, зависимость form wizard или доменные модели.