Cabinet Internal Modules
This section contains the lower-level cabinet registry, dashboard providers, Redis managers, view helpers, and model support classes.
Registry
codex_django.cabinet.registry
In-memory registry for cabinet navigation and dashboard contributions.
Feature apps interact with this module through :func:declare.
The registry stores sections, widgets, actions, sidebar items, and shortcuts
for rendering via context processors and views.
Supports two APIs:
- Legacy (v1): declare(module, section=CabinetSection(...))
- New (v2): declare(module, space="staff", topbar=TopbarEntry(...), sidebar=[...])
Classes
CabinetRegistry
Store cabinet contributions in process memory.
Source code in src/codex_django/cabinet/registry.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | |
Attributes
sections
property
Return all registered sections ordered by their display order.
dashboard_widgets
property
Return all registered dashboard widgets ordered by their display order.
topbar_actions
property
Return topbar action declarations in registration order.
global_actions
property
Return global action declarations in registration order.
Functions
register_branding(space, label=None, icon=None)
Set branding metadata for a specific space.
Source code in src/codex_django/cabinet/registry.py
52 53 54 55 56 57 58 59 60 61 62 | |
get_branding(space)
Return branding metadata for a specific space.
Source code in src/codex_django/cabinet/registry.py
64 65 66 | |
register_v2(module, space, topbar=None, sidebar=None, shortcuts=None, dashboard_widgets=None, settings_url=None)
Register cabinet contributions for the new two-space model.
Source code in src/codex_django/cabinet/registry.py
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | |
get_topbar_entries(group=None)
Return topbar entries, optionally filtered by group.
Source code in src/codex_django/cabinet/registry.py
106 107 108 109 110 111 112 113 | |
get_sidebar(space, module)
Return sidebar items for a given space and module.
Source code in src/codex_django/cabinet/registry.py
115 116 117 | |
get_shortcuts(space, module)
Return topbar shortcuts for a given space and module.
Source code in src/codex_django/cabinet/registry.py
119 120 121 | |
get_settings_url(space, module)
Return the custom settings URL for a given space and module.
Source code in src/codex_django/cabinet/registry.py
123 124 125 | |
get_module_topbar(module)
Return the TopbarEntry associated with a specific module.
Source code in src/codex_django/cabinet/registry.py
127 128 129 | |
register(module_name, section=None, dashboard_widget=None, topbar_actions=None, actions=None)
Register cabinet contributions (legacy API).
.. deprecated:: Use :meth:register_v2 with the two-space model.
Source code in src/codex_django/cabinet/registry.py
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | |
get_sections(nav_group=None)
Return registered sections, optionally filtered by nav group.
Source code in src/codex_django/cabinet/registry.py
167 168 169 170 171 172 | |
get_dashboard_widgets(nav_group=None)
Return registered dashboard widgets, optionally filtered by nav group.
Source code in src/codex_django/cabinet/registry.py
179 180 181 182 183 184 | |
Functions
declare(module, space=None, topbar=None, sidebar=None, shortcuts=None, settings_url=None, dashboard_widgets=None, section=None, dashboard_widget=None, **kwargs)
Public API for cabinet.py in feature apps. Analogous to admin.site.register().
New two-space API (when space is provided)::
declare(
module="booking",
space="staff",
topbar=TopbarEntry(group="services", label="Booking", ...),
sidebar=[SidebarItem(label="Schedule", url="booking:schedule", ...)],
shortcuts=[Shortcut(label="New", url="booking:new", icon="bi-plus")],
)
Legacy API (when space is None)::
declare(module="booking", section=CabinetSection(...))
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module
|
str
|
Django app name or feature identifier. |
required |
space
|
str | None
|
|
None
|
topbar
|
TopbarEntry | None
|
Topbar dropdown entry (v2 only). |
None
|
sidebar
|
list[SidebarItem] | None
|
Sidebar navigation items (v2 only). |
None
|
shortcuts
|
list[Shortcut] | None
|
Topbar shortcuts for this module (v2 only). |
None
|
section
|
CabinetSection | None
|
Legacy :class: |
None
|
dashboard_widgets
|
list[DashboardWidget] | DashboardWidget | str | None
|
Dashboard widget declaration (v2). |
None
|
dashboard_widget
|
DashboardWidget | str | None
|
Legacy dashboard widget declaration (v1). |
None
|
**kwargs
|
Any
|
Additional keyword arguments forwarded to registry. |
{}
|
Source code in src/codex_django/cabinet/registry.py
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 | |
configure_space(space, label=None, icon=None)
Configure space-wide metadata (branding, icon, etc).
Example::
configure_space(
space="staff",
label=_("Admin Panel"),
icon="bi-shield-lock",
)
Source code in src/codex_django/cabinet/registry.py
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 | |
Types — Navigation
codex_django.cabinet.types.nav
Navigation contracts for the cabinet two-space model.
This module defines the dataclasses that feature apps use to register
navigation entries in the cabinet shell. All types here are immutable
(frozen=True) to prevent accidental mutation of the global registry.
Two-space model
- staff space (
/cabinet/) — owners and administrators. Uses :class:TopbarEntryfor the top navigation bar and :class:SidebarItemfor the per-module sub-navigation. - client space (
/cabinet/my/) — end-customers. Uses :class:SidebarItemonly (no topbar dropdowns).
Typical usage in a feature app::
# features/booking/cabinet.py
from codex_django.cabinet import declare, TopbarEntry, SidebarItem, Shortcut
declare(
space="staff",
module="booking",
topbar=TopbarEntry(
group="services",
label="Booking",
icon="bi-calendar-check",
url="/cabinet/booking/",
order=10,
),
sidebar=[
SidebarItem(label="Schedule", url="booking:schedule", icon="bi-calendar3"),
SidebarItem(label="New Booking", url="booking:new", icon="bi-plus-circle"),
SidebarItem(label="Pending", url="booking:pending", icon="bi-hourglass-split",
badge_key="pending_count"),
],
shortcuts=[
Shortcut(label="New", url="booking:new", icon="bi-plus"),
],
)
declare(
space="client",
module="booking",
sidebar=[
SidebarItem(label="My Appointments", url="booking:my_bookings",
icon="bi-calendar2-check"),
],
)
Classes
TopbarEntry
dataclass
A navigation entry rendered inside a staff topbar dropdown group.
The staff topbar contains two dropdown menus: admin (for management
pages like analytics, users, and settings) and services (for feature
modules like booking, catalog, etc.). Each :class:TopbarEntry declares
which dropdown it belongs to via the group field.
Entries within the same group are sorted ascending by order.
This class is frozen — instances are immutable after creation.
Attributes:
| Name | Type | Description |
|---|---|---|
group |
str
|
Dropdown group identifier. Must be |
label |
str | Promise
|
Human-readable display name shown in the topbar link. |
icon |
str
|
Bootstrap Icons class name, e.g. |
url |
str
|
Absolute URL or named URL string resolved by the template. |
order |
int
|
Sort order within the group. Lower values appear first.
Defaults to |
Raises:
| Type | Description |
|---|---|
ImproperlyConfigured
|
If |
Example::
TopbarEntry(
group="services",
label="Booking",
icon="bi-calendar-check",
url="/cabinet/booking/",
order=10,
)
Source code in src/codex_django/cabinet/types/nav.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | |
SidebarItem
dataclass
A sub-navigation link rendered in the cabinet module sidebar.
When a view sets request.cabinet_module = "booking", the context
processor fetches SidebarItem list registered for that space+module
combination and exposes it as cabinet_sidebar. The _sidebar_staff.html
or _sidebar_client.html template then renders each item via
{% include "cabinet/includes/_nav_item.html" %}.
Items are sorted ascending by order at registration time.
This class is frozen — instances are immutable after creation.
Attributes:
| Name | Type | Description |
|---|---|---|
label |
str | Promise
|
Display name of the navigation link. |
url |
str
|
Named URL (e.g. |
icon |
str
|
Bootstrap Icons class name, e.g. |
badge_key |
str
|
Context variable name to read a numeric badge count from.
If the context contains |
order |
int
|
Sort order within the sidebar. Lower values appear first.
Defaults to |
permissions |
tuple[str, ...]
|
Tuple of Django permission strings. The item is hidden unless the user has at least one of the listed permissions. Empty tuple (default) means visible to all authenticated users. |
Example::
SidebarItem(
label="Pending",
url="booking:pending",
icon="bi-hourglass-split",
badge_key="pending_count",
order=3,
permissions=("booking.view_appointment",),
)
Source code in src/codex_django/cabinet/types/nav.py
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | |
Shortcut
dataclass
A quick-action link rendered in the staff topbar for the active module.
Shortcuts appear as small icon+label buttons in the topbar when the user is inside a specific cabinet module. They provide one-click access to the most common actions (e.g. "New Booking", "Add Client").
Shortcuts are registered per space+module via :func:codex_django.cabinet.declare
and exposed to templates as cabinet_shortcuts.
This class is frozen — instances are immutable after creation.
Attributes:
| Name | Type | Description |
|---|---|---|
label |
str | Promise
|
Short display name, e.g. |
url |
str
|
Named URL or absolute path for the link target. |
icon |
str
|
Bootstrap Icons class name, e.g. |
Example::
Shortcut(label="New Booking", url="booking:new", icon="bi-plus-circle")
Source code in src/codex_django/cabinet/types/nav.py
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | |
Types — Widgets
codex_django.cabinet.types.widgets
Data contracts for dashboard widget payloads.
This module defines the dataclasses that dashboard selectors return and
widget templates consume. Widgets live in
cabinet/templates/cabinet/widgets/ and are registered via
:class:~codex_django.cabinet.types.registry.DashboardWidget.
The typical data flow is::
selector function → returns widget payload dataclass
↓
DashboardSelector cache layer
↓
context processor injects into template context
↓
dashboard/index.html renders {% include widget.template %}
↓
widget template reads typed payload from context
Widget types:
- :class:
MetricWidgetData— single KPI number with optional trend. - :class:
TableWidgetData— tabular data with typed column definitions. - :class:
ListWidgetData— vertical list of labelled items with optional avatars.
Supporting types:
- :class:
TableColumn— column descriptor reused by both :class:TableWidgetData(dashboard) and :class:~codex_django.cabinet.types.components.DataTableData(page component). - :class:
ListItem— single row in a :class:ListWidgetData.
Classes
TableColumn
dataclass
Descriptor for a single column in a table widget or data table component.
Shared by :class:TableWidgetData (dashboard widget) and
:class:~codex_django.cabinet.types.components.DataTableData (full-page
component). The template uses col.key to read the corresponding value
from each row dict.
Attributes:
| Name | Type | Description |
|---|---|---|
key |
str
|
Dict key used to look up the cell value in each row.
Example: |
label |
str
|
Column header text shown to the user. |
align |
str
|
Horizontal text alignment. One of |
bold |
bool
|
If |
muted |
bool
|
If |
sortable |
bool
|
If |
badge_key |
str | None
|
If set, the cell value is rendered as a coloured badge.
The value of this attribute is the context key that maps the cell
value to a Bootstrap colour name (e.g. |
icon_key |
str | None
|
If set, an icon is prepended to the cell value. The value
is the context key for a Bootstrap Icons class mapping.
Defaults to |
Example::
TableColumn(key="status", label="Статус", badge_key="status_color_map")
TableColumn(key="name", label="Клиент", bold=True)
TableColumn(key="amount", label="Сумма", align="right")
Source code in src/codex_django/cabinet/types/widgets.py
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | |
ListItem
dataclass
A single row in a dashboard list widget.
Used as elements of :attr:ListWidgetData.items. Each item displays
a primary label, a primary value, and optional secondary lines and avatar.
Attributes:
| Name | Type | Description |
|---|---|---|
label |
str
|
Primary descriptor on the left side, e.g. client name or service title. |
value |
str
|
Primary metric on the right side, e.g. |
avatar |
str | None
|
Optional URL to an avatar image, or a 1–2 character initials
string. When set, an avatar circle is rendered before the label.
Defaults to |
sublabel |
str | None
|
Optional secondary text below |
subvalue |
str | None
|
Optional secondary text below |
Example::
ListItem(label="Иван Петров", value="5 сеансов", avatar="ИП",
sublabel="Постоянный клиент")
Source code in src/codex_django/cabinet/types/widgets.py
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | |
MetricWidgetData
dataclass
Payload for a KPI metric widget (cabinet/widgets/kpi.html).
Displays a single headline number with an optional trend indicator (up/down/neutral arrow + label) and a decorative icon.
Attributes:
| Name | Type | Description |
|---|---|---|
label |
str
|
Short description of the metric, e.g. |
value |
str
|
Formatted metric value, e.g. |
unit |
str | None
|
Optional unit suffix displayed after |
trend_value |
str | None
|
Formatted change value, e.g. |
trend_label |
str | None
|
Short context for the trend, e.g. |
trend_direction |
str
|
Visual direction of the trend arrow. One of
|
icon |
str | None
|
Bootstrap Icons class name for the decorative icon,
e.g. |
Example::
MetricWidgetData(
label="Новые клиенты",
value="142",
trend_value="+12%",
trend_label="за неделю",
trend_direction="up",
icon="bi-people",
)
Source code in src/codex_django/cabinet/types/widgets.py
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | |
TableWidgetData
dataclass
Payload for a table dashboard widget (cabinet/widgets/table.html).
Renders a compact data table inside a dashboard card. For a full-page
sortable/filterable table, use
:class:~codex_django.cabinet.types.components.DataTableData instead.
Attributes:
| Name | Type | Description |
|---|---|---|
columns |
list[TableColumn]
|
Ordered list of :class: |
rows |
list[dict[str, Any]]
|
List of dicts where each key corresponds to a
:attr: |
Example::
TableWidgetData(
columns=[
TableColumn(key="name", label="Клиент", bold=True),
TableColumn(key="date", label="Дата"),
TableColumn(key="amount", label="Сумма", align="right"),
],
rows=[
{"name": "Иван П.", "date": "01.04.2026", "amount": "3 500 ₽"},
{"name": "Анна С.", "date": "31.03.2026", "amount": "1 200 ₽"},
],
)
Source code in src/codex_django/cabinet/types/widgets.py
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | |
ListWidgetData
dataclass
Payload for a list dashboard widget (cabinet/widgets/list.html).
Renders a vertical list of labelled items with optional avatar circles
inside a dashboard card. For a full-page list, use
:class:~codex_django.cabinet.types.components.ListViewData instead.
Attributes:
| Name | Type | Description |
|---|---|---|
items |
list[ListItem]
|
Ordered list of :class: |
title |
str | None
|
Optional card title rendered above the list.
Defaults to |
Example::
ListWidgetData(
title="Топ клиенты",
items=[
ListItem(label="Иван Петров", value="12 000 ₽", avatar="ИП"),
ListItem(label="Анна Смирнова", value="8 500 ₽", avatar="АС"),
],
)
Source code in src/codex_django/cabinet/types/widgets.py
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | |
Types — Page Components
codex_django.cabinet.types.components
Data contracts for cabinet content-component templates.
Each dataclass in this module defines the payload that a template in
cabinet/templates/cabinet/components/ expects to receive via Django's
{% include ... with obj=obj %} tag.
Design principles:
- Backend computes, template renders. All positioning, counts, and formatting are calculated by the view or selector before the template sees them. Templates contain no business logic.
- One contract per component. Each
includereceives exactly one typed object. The template variable name matches the parameter name documented in each class. - Alpine.js for client-side state only. Toggle states (grid/list view,
search filter) live in
x-datainside the template. No custom JS files. - HTMX for server interactions. Detail panels, modals, and actions
use
hx-get/hx-post. URLs are passed through the contract. - Modal dispatch pattern. Components do not embed modals. They
dispatch
$dispatch('open-modal', {url: '...'})and the page-level_modal_base.htmlhandles loading.
Available components:
- :class:
DataTableData→components/data_table.html - :class:
CalendarGridData+ :class:CalendarSlot→components/calendar_grid.html - :class:
CardGridData+ :class:CardItem→components/card_grid.html - :class:
ListViewData+ :class:ListRow→components/list_view.html - :class:
SplitPanelData+ :class:ListRow→components/split_panel.html
Classes
TableFilter
dataclass
A single filter tab or button for :class:DataTableData.
Filter buttons are rendered as a row of toggle buttons above the table.
Clicking a filter sets activeFilter in Alpine state; the table
rows whose status field matches value remain visible.
Attributes:
| Name | Type | Description |
|---|---|---|
key |
str
|
Machine-readable identifier for the filter, e.g. |
label |
str
|
Human-readable button label, e.g. |
value |
str
|
The value to compare against the row's status field. Empty string (default) acts as "show all". |
Example::
TableFilter(key="pending", label="Ожидают", value="pending")
Source code in src/codex_django/cabinet/types/components.py
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | |
TableAction
dataclass
A row-level action link in a data table or list component.
Each action renders as a button or link in the last column of the table
(or in the row's action area). The URL for the action is read from the
row dict using url_key as the lookup key.
Attributes:
| Name | Type | Description |
|---|---|---|
label |
str
|
Button label text, e.g. |
url_key |
str
|
Key in the row dict whose value is used as the action URL.
Example: if |
icon |
str
|
Bootstrap Icons class name, e.g. |
style |
str
|
Visual style. One of:
|
Example::
TableAction(label="Открыть", url_key="detail_url", icon="bi-eye")
TableAction(label="Удалить", url_key="delete_url", icon="bi-trash",
style="btn-danger")
Source code in src/codex_django/cabinet/types/components.py
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | |
DataTableData
dataclass
Payload contract for components/data_table.html.
Renders a searchable, filterable data table. Search and filter state is managed client-side by Alpine.js (no page reload). Row actions open detail modals via HTMX dispatch.
Template variable: table::
{% include "cabinet/components/data_table.html" with table=table %}
Attributes:
| Name | Type | Description |
|---|---|---|
columns |
list[TableColumn]
|
Ordered list of :class: |
rows |
list[dict[str, Any]]
|
List of dicts. Each dict must contain keys matching
:attr: |
filters |
list[TableFilter]
|
Optional list of :class: |
actions |
list[TableAction]
|
Optional list of :class: |
search_placeholder |
str
|
Placeholder text for the search input. Empty string (default) hides the search bar entirely. |
empty_message |
str
|
Message shown when |
Example::
from codex_django.cabinet import DataTableData, TableColumn, TableFilter, TableAction
table = DataTableData(
columns=[
TableColumn(key="name", label="Клиент", bold=True),
TableColumn(key="date", label="Дата"),
TableColumn(key="status", label="Статус", badge_key="status_colors"),
],
rows=list(Appointment.objects.values("name", "date", "status", "detail_url")),
filters=[
TableFilter(key="pending", label="Ожидают", value="pending"),
TableFilter(key="confirmed", label="Подтверждены", value="confirmed"),
],
actions=[TableAction(label="Открыть", url_key="detail_url", icon="bi-eye")],
search_placeholder="Поиск клиентов...",
)
return render(request, "booking/appointments.html", {"table": table})
Source code in src/codex_django/cabinet/types/components.py
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | |
CalendarSlot
dataclass
A single event positioned on a :class:CalendarGridData grid.
The grid uses CSS grid-column and grid-row to place events.
All positional values are zero-based indexes into
:attr:CalendarGridData.cols and :attr:CalendarGridData.rows.
The backend computes these values; the template only renders them.
Attributes:
| Name | Type | Description |
|---|---|---|
col |
int
|
Zero-based column index. Corresponds to the master, room, or
day at that position in :attr: |
row |
int
|
Zero-based row index. Corresponds to the time slot at that
position in :attr: |
span |
int
|
Number of consecutive rows the event occupies. Compute as::
For a 1-hour appointment with 30-minute slots: |
title |
str
|
Primary event text (e.g. client name or appointment type). |
subtitle |
str
|
Optional secondary text (e.g. service name). Defaults to empty string. |
color |
str
|
CSS color value or Bootstrap |
url |
str
|
HTMX endpoint to load when the event is clicked. Opens the
detail/edit form in |
Example::
# 60-minute appointment starting at 9:00 with 30-min slots (row index 2)
CalendarSlot(
col=0, # first master
row=2, # 9:00 slot (rows: ["8:00","8:30","9:00",...])
span=2, # 60 min / 30 min = 2
title="Иван П.",
subtitle="Стрижка",
color="#6366f1",
url="/booking/42/",
)
Source code in src/codex_django/cabinet/types/components.py
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | |
CalendarGridData
dataclass
Payload contract for components/calendar_grid.html.
Renders a CSS Grid-based scheduling calendar. Columns represent any grouping axis (masters, rooms, weekdays), rows represent time slots at any granularity. The same contract is shared by two templates:
calendar_grid.html— vertical grid (cols × rows).calendar_timeline.html— horizontal timeline (future).
The backend computes all event positions. The template renders a background grid of clickable empty slots and overlays events on top.
Template variable: calendar::
{% include "cabinet/components/calendar_grid.html" with calendar=calendar %}
{% include "cabinet/includes/_modal_base.html" %}
Attributes:
| Name | Type | Description |
|---|---|---|
cols |
list[str | dict[str, Any]]
|
Column header labels. Can be master names, room names,
weekday names, or any list of strings.
Example: |
rows |
list[str]
|
Time slot labels in display order.
Example: |
events |
list[CalendarSlot]
|
List of :class: |
slot_height_px |
int
|
Height of each time slot row in pixels.
Adjust for denser or sparser grids. Defaults to |
new_event_url |
str
|
HTMX base URL for creating a new event.
When set, each empty slot becomes clickable and sends
|
Example::
from codex_django.cabinet import CalendarGridData, CalendarSlot
# Build 30-min slots from 8:00 to 20:00
rows = [f"{h}:{m:02d}" for h in range(8, 20) for m in (0, 30)]
calendar = CalendarGridData(
cols=["Мастер 1", "Мастер 2", "Мастер 3"],
rows=rows,
events=[
CalendarSlot(col=0, row=2, span=2,
title="Иван П.", subtitle="Стрижка",
color="#6366f1", url="/booking/42/"),
],
slot_height_px=40,
new_event_url="/booking/new/",
)
return render(request, "booking/schedule.html", {"calendar": calendar})
Source code in src/codex_django/cabinet/types/components.py
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | |
CardItem
dataclass
A single card in a :class:CardGridData collection.
Renders as a card tile in grid mode or as a list row in list mode.
The meta field carries icon+text pairs for secondary information
(e.g. phone number, appointment count, last visit date).
Attributes:
| Name | Type | Description |
|---|---|---|
id |
str
|
Unique string identifier used as an HTML key. Should be the
primary key of the underlying model, e.g. |
title |
str
|
Primary card heading (e.g. client full name). |
subtitle |
str
|
Optional secondary line below the title (e.g. client category or role). Defaults to empty string. |
avatar |
str
|
URL to an avatar image, or 1–2 character initials string for the avatar circle. Defaults to empty string (no avatar). |
badge |
str
|
Short status label rendered as a badge, e.g. |
badge_style |
str
|
Bootstrap colour name for the badge background,
e.g. |
url |
str
|
Link target for the card. Can be a detail page URL or an HTMX endpoint. Defaults to empty string (non-clickable). |
meta |
list[tuple[str, str]]
|
List of |
Example::
CardItem(
id=str(client.pk),
title=client.full_name,
subtitle=client.category,
avatar=client.initials,
badge="VIP",
badge_style="warning",
url=f"/cabinet/clients/{client.pk}/",
meta=[
("bi-telephone", client.phone),
("bi-calendar", f"{client.visit_count} визитов"),
],
)
Source code in src/codex_django/cabinet/types/components.py
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 | |
CardGridData
dataclass
Payload contract for components/card_grid.html.
Renders a collection of :class:CardItem instances either as a
Bootstrap grid of cards or as a compact list. The user can toggle
between modes client-side via Alpine.js (no page reload).
Template variable: cards::
{% include "cabinet/components/card_grid.html" with cards=cards %}
Attributes:
| Name | Type | Description |
|---|---|---|
items |
list[CardItem]
|
List of :class: |
view_mode |
str
|
Initial render mode. |
search_placeholder |
str
|
Placeholder text for the client-side search
input. Alpine.js filters cards by |
empty_message |
str
|
Message shown when |
Example::
from codex_django.cabinet import CardGridData, CardItem
cards = CardGridData(
items=[
CardItem(
id=str(c.pk),
title=c.full_name,
avatar=c.initials,
url=f"/cabinet/clients/{c.pk}/",
)
for c in Client.objects.all()
],
search_placeholder="Поиск клиентов...",
)
return render(request, "clients/index.html", {"cards": cards})
Source code in src/codex_django/cabinet/types/components.py
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 | |
ListRow
dataclass
A single row in a :class:ListViewData or :class:SplitPanelData.
Displays a primary label, optional secondary text, and optional meta information. Rows can be clickable (HTMX detail load or plain link) and carry per-row action buttons.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
str
|
Unique string identifier (typically the model's primary key). |
primary |
str
|
Main row text, e.g. subject line or client name. |
secondary |
str
|
Optional secondary text rendered smaller below
|
meta |
str
|
Optional short metadata shown on the right (e.g. date, count). Defaults to empty string. |
avatar |
str
|
URL or initials string for the avatar circle. Defaults to empty string (no avatar). |
url |
str
|
HTMX endpoint or plain link URL. In :class: |
actions |
list[TableAction]
|
Per-row :class: |
Example::
ListRow(
id=str(msg.pk),
primary=msg.subject,
secondary=msg.sender,
meta=msg.created_at.strftime("%d.%m"),
url=f"/cabinet/conversations/{msg.pk}/",
)
Source code in src/codex_django/cabinet/types/components.py
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 | |
ListViewData
dataclass
Payload contract for components/list_view.html.
Renders a vertical list of :class:ListRow instances with an optional
search bar. Clicking a row either opens a modal (HTMX) or navigates
to the row's URL. Row-level action buttons appear on hover.
Template variable: list::
{% include "cabinet/components/list_view.html" with list=list_data %}
{% include "cabinet/includes/_modal_base.html" %}
Attributes:
| Name | Type | Description |
|---|---|---|
rows |
list[ListRow]
|
Ordered list of :class: |
search_placeholder |
str
|
Placeholder text for the Alpine.js search
input. Filters rows by |
empty_message |
str
|
Message shown when |
Example::
from codex_django.cabinet import ListViewData, ListRow
list_data = ListViewData(
rows=[
ListRow(
id=str(n.pk),
primary=n.subject,
secondary=n.channel,
meta=n.sent_at.strftime("%d.%m %H:%M"),
url=f"/cabinet/notifications/{n.pk}/",
)
for n in Notification.objects.order_by("-sent_at")
],
search_placeholder="Поиск уведомлений...",
)
return render(request, "notifications/log.html", {"list": list_data})
Source code in src/codex_django/cabinet/types/components.py
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 | |
SplitPanelData
dataclass
Payload contract for components/split_panel.html.
Renders a two-column layout: a scrollable item list on the left and a
detail area on the right. Clicking a list item loads its detail via
HTMX into #split-panel-detail without a full page reload.
On mobile (< 768 px) the panels stack vertically.
Template variable: panel::
{% include "cabinet/components/split_panel.html" with panel=panel %}
Note
Place {% include "cabinet/includes/_modal_base.html" %} on the
page if the detail area opens sub-modals.
Attributes:
| Name | Type | Description |
|---|---|---|
items |
list[ListRow]
|
List of :class: |
active_id |
str
|
|
detail_url |
str
|
HTMX base URL for loading item details. The component
appends |
empty_message |
str
|
Message shown in the right panel when no item is
selected. Defaults to |
Example::
from codex_django.cabinet import SplitPanelData, ListRow
panel = SplitPanelData(
items=[
ListRow(
id=str(conv.pk),
primary=conv.subject,
secondary=conv.last_message[:60],
meta=conv.updated_at.strftime("%d.%m"),
avatar=conv.client_initials,
)
for conv in conversations
],
active_id=str(active_conversation.pk) if active_conversation else "",
detail_url="/cabinet/conversations",
empty_message="Выберите переписку",
)
return render(request, "conversations/index.html", {"panel": panel})
Source code in src/codex_django/cabinet/types/components.py
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 | |
ServiceItem
dataclass
A single service or product in a selector.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
str
|
Unique ID (e.g. PK). |
title |
str
|
Display name (e.g. "Маникюр + Гель-лак"). |
price |
str
|
Price string (e.g. "45"). |
duration |
int
|
Duration in minutes (e.g. 90). |
category |
str
|
Machine name for filtering (e.g. "nails"). |
Source code in src/codex_django/cabinet/types/components.py
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 | |
ServiceSelectorData
dataclass
Payload for components/widgets/service_selector.html.
Attributes:
| Name | Type | Description |
|---|---|---|
items |
list[ServiceItem]
|
List of :class: |
categories |
list[tuple[str, str]]
|
Ordered list of |
search_placeholder |
str
|
Placeholder for the search input. |
Source code in src/codex_django/cabinet/types/components.py
593 594 595 596 597 598 599 600 601 602 603 604 605 | |
ClientSelectorData
dataclass
Payload for components/widgets/client_selector.html.
Attributes:
| Name | Type | Description |
|---|---|---|
clients |
list[dict[str, Any]]
|
List of existing clients for search/selection. |
search_placeholder |
str
|
Placeholder for the search input. |
Source code in src/codex_django/cabinet/types/components.py
608 609 610 611 612 613 614 615 616 617 618 | |
DateTimePickerData
dataclass
Payload for components/widgets/date_time_picker.html.
Attributes:
| Name | Type | Description |
|---|---|---|
available_days |
list[dict[str, Any]]
|
List of days to show in the mini-calendar. |
time_slots |
list[str]
|
List of time strings (e.g. "08:00"). |
busy_slots |
list[str]
|
List of time strings that are unavailable. |
current_month |
str
|
Month label (e.g. "March 2026"). |
Source code in src/codex_django/cabinet/types/components.py
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 | |
BookingSummaryData
dataclass
Payload for components/widgets/summary_panel.html.
Attributes:
| Name | Type | Description |
|---|---|---|
confirm_url |
str
|
POST endpoint for the booking. |
reset_url |
str
|
URL to clear the selection. |
masters |
list[dict[str, Any]]
|
List of available specialists for manual assignment. |
Source code in src/codex_django/cabinet/types/components.py
640 641 642 643 644 645 646 647 648 649 650 651 652 | |
BookingQuickCreateServiceOption
dataclass
Service option shown inside a quick-create booking modal.
Source code in src/codex_django/cabinet/types/components.py
655 656 657 658 659 660 661 662 | |
BookingQuickCreateClientOption
dataclass
Client option shown inside a quick-create booking modal.
Source code in src/codex_django/cabinet/types/components.py
665 666 667 668 669 670 671 672 673 | |
BookingQuickCreateData
dataclass
Payload for a quick-create single-appointment block inside a modal.
Source code in src/codex_django/cabinet/types/components.py
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 | |
BookingSlotPickerOption
dataclass
Single slot option in a booking slot-picker block.
Source code in src/codex_django/cabinet/types/components.py
699 700 701 702 703 704 705 | |
BookingSlotPickerData
dataclass
Payload for a booking-native date navigation and slot selection block.
Source code in src/codex_django/cabinet/types/components.py
708 709 710 711 712 713 714 715 716 717 718 719 | |
BookingChainPreviewItem
dataclass
Single row in a booking chain preview block.
Source code in src/codex_django/cabinet/types/components.py
722 723 724 725 726 727 728 | |
BookingChainPreviewData
dataclass
Payload for a booking chain preview block.
Source code in src/codex_django/cabinet/types/components.py
731 732 733 734 735 736 | |
ModalSection
dataclass
Base class for modal sections.
Source code in src/codex_django/cabinet/types/components.py
744 745 746 747 748 | |
ProfileSection
dataclass
Bases: ModalSection
Client/Staff profile header in a modal.
Source code in src/codex_django/cabinet/types/components.py
751 752 753 754 755 756 757 758 | |
SummarySection
dataclass
Bases: ModalSection
Grid of key-value pairs (e.g. Appointment details).
Source code in src/codex_django/cabinet/types/components.py
767 768 769 770 771 772 | |
FormSection
dataclass
Bases: ModalSection
Input fields group.
Source code in src/codex_django/cabinet/types/components.py
785 786 787 788 789 790 | |
ModalAction
dataclass
A button in the modal footer or action group.
Source code in src/codex_django/cabinet/types/components.py
793 794 795 796 797 798 799 800 801 | |
ActionSection
dataclass
Bases: ModalSection
Group of action buttons.
Source code in src/codex_django/cabinet/types/components.py
804 805 806 807 808 809 | |
SlotPickerSection
dataclass
Bases: ModalSection
Booking-native date navigator and slot picker for modal workflows.
Source code in src/codex_django/cabinet/types/components.py
812 813 814 815 816 817 818 819 | |
QuickCreateSection
dataclass
Bases: ModalSection
Booking quick-create block for creating one appointment from a calendar slot.
Source code in src/codex_django/cabinet/types/components.py
822 823 824 825 826 827 828 829 | |
ChainPreviewSection
dataclass
Bases: ModalSection
Booking chain preview block used by richer booking builders/modals.
Source code in src/codex_django/cabinet/types/components.py
832 833 834 835 836 837 | |
ModalContentData
dataclass
Payload for components/generic_modal.html.
Assembles a modal window from multiple functional sections.
Source code in src/codex_django/cabinet/types/components.py
840 841 842 843 844 845 846 847 848 | |
Types — Registry
codex_django.cabinet.types.registry
Registration contracts for the cabinet registry.
This module defines the dataclasses used when feature apps register
dashboard widgets and navigation sections with the global
:data:~codex_django.cabinet.registry.cabinet_registry.
Types:
- :class:
DashboardWidget— declares a widget to render on the dashboard. - :class:
NavAction— a generic action link in cabinet navigation areas. - :class:
CabinetSection— deprecated v1 navigation section. Use :class:~codex_django.cabinet.types.nav.TopbarEntrywith the newdeclare(space=...)API instead.
Classes
DashboardWidget
dataclass
Declaration of a dashboard widget contributed by a feature app.
Feature apps register widgets via :func:~codex_django.cabinet.declare.
The registry stores them and the dashboard view renders all widgets
that the current user has permission to see.
The template path is resolved relative to Django's template loaders.
Widget templates live in cabinet/templates/cabinet/widgets/ for
built-in widgets, or in the feature app's own templates/ directory
for custom widgets.
This class is frozen — instances are immutable after creation.
Attributes:
| Name | Type | Description |
|---|---|---|
template |
str
|
Django template path, e.g.
|
col |
str
|
Bootstrap column class controlling widget width.
Defaults to |
lazy |
bool
|
If |
nav_group |
str
|
Navigation group this widget belongs to. Determines which dashboard tab shows the widget. Must be one of:
|
permissions |
tuple[str, ...]
|
Tuple of Django permission strings. The widget is hidden unless the user has at least one listed permission. Empty tuple (default) means visible to all authenticated users. |
order |
int
|
Sort order on the dashboard. Lower values appear first.
Defaults to |
Raises:
| Type | Description |
|---|---|
ImproperlyConfigured
|
If |
Example::
DashboardWidget(
template="booking/widgets/upcoming_appointments.html",
col="col-lg-6",
lazy=True,
nav_group="services",
permissions=("booking.view_appointment",),
order=10,
)
Source code in src/codex_django/cabinet/types/registry.py
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | |
NavAction
dataclass
A generic action link rendered in cabinet navigation areas.
Used for supplementary links that do not belong to the main topbar or sidebar navigation — for example, footer links, context-specific quick actions, or legacy v1 topbar buttons.
This class is frozen — instances are immutable after creation.
Attributes:
| Name | Type | Description |
|---|---|---|
label |
str
|
Display name of the action, e.g. |
url |
str
|
Absolute URL or named URL string for the link. |
icon |
str | None
|
Optional Bootstrap Icons class name, e.g. |
Example::
NavAction(label="Настройки", url="/cabinet/settings/", icon="bi-gear")
Source code in src/codex_django/cabinet/types/registry.py
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | |
CabinetSection
dataclass
Deprecated. V1 navigation section for the cabinet topbar.
.. deprecated::
Use :class:~codex_django.cabinet.types.nav.TopbarEntry together
with the new declare(space=...) API. CabinetSection is kept
only for backward compatibility with projects generated by older
versions of codex-django-cli.
In the v1 API a CabinetSection was passed directly to declare()::
# Old — do not use in new code
from codex_django.cabinet import declare, CabinetSection
declare(
module="booking",
section=CabinetSection(
label="Booking",
icon="bi-calendar",
nav_group="services",
url="/cabinet/booking/",
order=10,
),
)
Migrate to the v2 API::
# New
from codex_django.cabinet import declare, TopbarEntry, SidebarItem
declare(
space="staff",
module="booking",
topbar=TopbarEntry(
group="services",
label="Booking",
icon="bi-calendar",
url="/cabinet/booking/",
order=10,
),
sidebar=[...],
)
This class is frozen — instances are immutable after creation.
Attributes:
| Name | Type | Description |
|---|---|---|
label |
str
|
Display name of the section. |
icon |
str
|
Bootstrap Icons class name, e.g. |
nav_group |
str
|
Dropdown group. Must be |
url |
str | None
|
Optional link URL. |
permissions |
tuple[str, ...]
|
Tuple of Django permission strings (OR logic).
Empty tuple means visible to all. Defaults to |
order |
int
|
Sort order. Defaults to |
Raises:
| Type | Description |
|---|---|
ImproperlyConfigured
|
If |
Source code in src/codex_django/cabinet/types/registry.py
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | |
Context processors
codex_django.cabinet.context_processors
Template context helpers for the cabinet UI shell.
Classes
Dashboard selector
codex_django.cabinet.selector.dashboard
Dashboard Selector
Single entry point for dashboard data providers.
Providers are registered through @extend and cached in Redis through
DashboardRedisManager using JSON rather than pickle.
Example project usage:
# cabinet/selector/dashboard.py inside the generated project
from codex_django.cabinet.selector.dashboard import DashboardSelector
from ..mock import CabinetMockData
@DashboardSelector.extend(cache_key="base_stats", cache_ttl=300)
def base_stats(request):
return {"dashboard_stats": CabinetMockData.get_dashboard_stats()}
Adding a provider from a feature module such as booking:
# features/booking/cabinet.py
@DashboardSelector.extend(cache_key="booking_kpi", cache_ttl=300)
def booking_kpi(request):
return {"booking_kpi": BookingSelector.get_dashboard_kpi(request)}
Invalidating cached data from a model save hook:
# features/booking/models/booking.py
from codex_django.cabinet.selector.dashboard import DashboardSelector
DashboardSelector.invalidate("booking_kpi")
Classes
DashboardAdapter
Bases: ABC
Base class for dashboard data adapters.
Adapters are responsible for fetching and formatting data for specific widget types before the selector merges them into the template context.
Source code in src/codex_django/cabinet/selector/dashboard.py
44 45 46 47 48 49 50 51 52 53 54 | |
Functions
get_data(request)
abstractmethod
Fetch and return widget data as a dictionary payload.
Source code in src/codex_django/cabinet/selector/dashboard.py
51 52 53 54 | |
MetricAdapter
Bases: DashboardAdapter
Generic adapter for metric widgets.
Source code in src/codex_django/cabinet/selector/dashboard.py
57 58 59 60 61 62 63 64 65 66 | |
Functions
get_data(request)
Wrap metric payloads under the metric key.
Source code in src/codex_django/cabinet/selector/dashboard.py
63 64 65 66 | |
TableAdapter
Bases: DashboardAdapter
Generic adapter for table widgets.
Source code in src/codex_django/cabinet/selector/dashboard.py
69 70 71 72 73 74 75 76 77 78 | |
Functions
get_data(request)
Wrap table payloads under the table key.
Source code in src/codex_django/cabinet/selector/dashboard.py
75 76 77 78 | |
ListAdapter
Bases: DashboardAdapter
Generic adapter for list widgets.
Source code in src/codex_django/cabinet/selector/dashboard.py
81 82 83 84 85 86 87 88 89 90 | |
Functions
get_data(request)
Wrap list payloads under the list key.
Source code in src/codex_django/cabinet/selector/dashboard.py
87 88 89 90 | |
DashboardSelector
Extensible dashboard data aggregator with Redis caching.
Each provider is a flat function (request) -> dict or a DashboardAdapter. Registered via @DashboardSelector.extend(cache_key=..., cache_ttl=...).
Source code in src/codex_django/cabinet/selector/dashboard.py
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | |
Functions
extend(fn_or_adapter=None, *, cache_key='', cache_ttl=120)
classmethod
Register a dashboard data provider.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cache_key
|
str
|
Redis key suffix. Defaults to function/class name. |
''
|
cache_ttl
|
int
|
Seconds to cache. 0 = no cache (real-time). |
120
|
Source code in src/codex_django/cabinet/selector/dashboard.py
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | |
get_context(request)
classmethod
Collect data from all registered providers. Each provider is read from Redis cache if available, otherwise called and cached.
Source code in src/codex_django/cabinet/selector/dashboard.py
140 141 142 143 144 145 146 147 148 149 150 | |
invalidate(cache_key)
classmethod
Invalidate cache for a specific provider. Call from model signals.
Source code in src/codex_django/cabinet/selector/dashboard.py
170 171 172 173 | |
invalidate_all()
classmethod
Invalidate all dashboard provider caches.
Source code in src/codex_django/cabinet/selector/dashboard.py
175 176 177 178 | |
Dashboard Redis manager
codex_django.cabinet.redis.managers.dashboard
Dashboard Redis Manager
Redis cache for dashboard data. Each provider is stored under its own key.
Serialization uses JSON instead of pickle, which keeps values readable from
redis-cli. Supported value types are str, int, float, bool,
list, dict, and Decimal converted to str.
Key format: {PROJECT_NAME}:cabinet:dashboard:{provider_key}
Classes
DashboardRedisManager
Bases: BaseDjangoRedisManager
Per-provider Redis cache for dashboard data.
Usage in DashboardSelector
_manager = DashboardRedisManager()
cached = _manager.get("booking_kpi") if cached is None: data = expensive_query() _manager.set("booking_kpi", data, ttl=300)
Invalidation from model signal / lifecycle hook: _manager.invalidate("booking_kpi") # one provider _manager.invalidate_all() # full dashboard refresh
Source code in src/codex_django/cabinet/redis/managers/dashboard.py
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | |
Functions
aget(provider_key)
async
Return cached provider data or None on cache miss.
Source code in src/codex_django/cabinet/redis/managers/dashboard.py
70 71 72 73 74 75 76 77 78 79 80 | |
get(provider_key)
Synchronously return cached provider data.
Source code in src/codex_django/cabinet/redis/managers/dashboard.py
82 83 84 | |
aset(provider_key, data, ttl)
async
Store provider data with a TTL in seconds.
Source code in src/codex_django/cabinet/redis/managers/dashboard.py
88 89 90 91 92 93 94 95 96 | |
set(provider_key, data, ttl)
Synchronously store provider data with a TTL in seconds.
Source code in src/codex_django/cabinet/redis/managers/dashboard.py
98 99 100 | |
ainvalidate(provider_key)
async
Delete cache for a single provider.
Source code in src/codex_django/cabinet/redis/managers/dashboard.py
104 105 106 107 108 | |
invalidate(provider_key)
Synchronously delete cache for a single provider.
Source code in src/codex_django/cabinet/redis/managers/dashboard.py
110 111 112 | |
ainvalidate_all()
async
Delete all dashboard provider caches using a key pattern.
Source code in src/codex_django/cabinet/redis/managers/dashboard.py
114 115 116 117 118 119 120 121 | |
invalidate_all()
Synchronously delete all dashboard provider caches.
Source code in src/codex_django/cabinet/redis/managers/dashboard.py
123 124 125 | |
Settings Redis manager
codex_django.cabinet.redis.managers.settings
Redis manager for cabinet settings payloads.
Classes
CabinetSettingsRedisManager
Bases: BaseDjangoRedisManager
Sync/async manager for CabinetSettings in Redis.
Key format: {PROJECT_NAME}:cabinet:settings Uses Redis Hash (same pattern as DjangoSiteSettingsManager). Respects DEBUG mode + CODEX_REDIS_ENABLED flag — safe for local dev without Redis.
Source code in src/codex_django/cabinet/redis/managers/settings.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | |
Functions
aget()
async
Asynchronously return the cached cabinet settings payload.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Cached cabinet settings data, or an empty dictionary when caching |
dict[str, Any]
|
is disabled or the Redis hash does not exist. |
Source code in src/codex_django/cabinet/redis/managers/settings.py
23 24 25 26 27 28 29 30 31 32 | |
get()
Synchronously return the cached cabinet settings payload.
Source code in src/codex_django/cabinet/redis/managers/settings.py
34 35 36 | |
asave_instance(instance)
async
Asynchronously persist a cabinet settings instance to Redis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
instance
|
Any
|
Object implementing |
required |
Source code in src/codex_django/cabinet/redis/managers/settings.py
38 39 40 41 42 43 44 45 46 47 48 | |
save_instance(instance)
Synchronously persist a cabinet settings instance to Redis.
Source code in src/codex_django/cabinet/redis/managers/settings.py
50 51 52 | |
ainvalidate()
async
Asynchronously invalidate the cached cabinet settings payload.
Source code in src/codex_django/cabinet/redis/managers/settings.py
54 55 56 57 58 | |
invalidate()
Synchronously invalidate the cached cabinet settings payload.
Source code in src/codex_django/cabinet/redis/managers/settings.py
60 61 62 | |
Settings model
codex_django.cabinet.models.settings
Singleton-like cabinet settings model and Redis synchronization hooks.
Classes
CabinetSettings
Bases: LifecycleModelMixin, Model
Cabinet settings — Singleton (always one instance, pk=1).
Stores cabinet-level configuration: name, logo, theme overrides. Auto-syncs to Redis on save via django_lifecycle hook. Skips Redis sync in DEBUG mode unless CODEX_REDIS_ENABLED=True.
Source code in src/codex_django/cabinet/models/settings.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
Functions
__str__()
Return the display name used in admin and debug output.
Source code in src/codex_django/cabinet/models/settings.py
25 26 27 | |
save(*args, **kwargs)
Persist the singleton settings row under primary key 1.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*args
|
Any
|
Positional arguments forwarded to |
()
|
**kwargs
|
Any
|
Keyword arguments forwarded to |
{}
|
Source code in src/codex_django/cabinet/models/settings.py
29 30 31 32 33 34 35 36 37 | |
delete(*args, **kwargs)
Refuse deletion so the singleton settings row always remains available.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*args
|
Any
|
Unused positional arguments accepted for API compatibility. |
()
|
**kwargs
|
Any
|
Unused keyword arguments accepted for API compatibility. |
{}
|
Returns:
| Type | Description |
|---|---|
int
|
The tuple Django expects from |
dict[str, int]
|
no rows were removed. |
Source code in src/codex_django/cabinet/models/settings.py
39 40 41 42 43 44 45 46 47 48 49 50 | |
load()
classmethod
Load or create the singleton settings instance from the database.
Returns:
| Type | Description |
|---|---|
CabinetSettings
|
The singleton :class: |
Source code in src/codex_django/cabinet/models/settings.py
52 53 54 55 56 57 58 59 60 | |
to_cabinet_dict()
Serialize the model to a Redis-friendly flat mapping.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
A dictionary that can be stored in the cabinet settings Redis hash. |
Source code in src/codex_django/cabinet/models/settings.py
62 63 64 65 66 67 68 69 70 71 72 73 74 | |
sync_to_redis()
Persist the latest cabinet settings payload to Redis after save.
Source code in src/codex_django/cabinet/models/settings.py
76 77 78 79 80 81 82 83 84 85 86 | |
Shared model mixins
codex_django.cabinet.models.mixins
Field mixins for cabinet domain models.
These mixins define the expected interface (which fields are required), not the business logic (choices, validation). Developers declare their own status choices etc. on the concrete model.
Usage in project
from codex_django.cabinet.models import AppointmentFieldsMixin
class Appointment(AppointmentFieldsMixin): STATUS_PENDING = 'pending' STATUS_CONFIRMED = 'confirmed' STATUS_CHOICES = [(STATUS_PENDING, 'Pending'), (STATUS_CONFIRMED, 'Confirmed')] status = models.CharField(max_length=20, choices=STATUS_CHOICES, default=STATUS_PENDING)
Classes
AppointmentFieldsMixin
Bases: Model
Base fields mixin for appointments/bookings. No choices — developer defines them.
Source code in src/codex_django/cabinet/models/mixins.py
23 24 25 26 27 28 29 30 31 | |
ClientFieldsMixin
Bases: Model
Base fields mixin for client profiles.
Source code in src/codex_django/cabinet/models/mixins.py
34 35 36 37 38 39 40 41 42 43 44 45 | |
ServiceFieldsMixin
Bases: Model
Base fields mixin for services/offerings.
Source code in src/codex_django/cabinet/models/mixins.py
48 49 50 51 52 53 54 55 56 57 | |
Dashboard views
codex_django.cabinet.views.dashboard
Views for the main cabinet dashboard shell.
Classes
Functions
dashboard_view(request)
Render the dashboard page with aggregated provider context.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
HttpRequest
|
Authenticated Django request for the cabinet dashboard. |
required |
Returns:
| Type | Description |
|---|---|
HttpResponse
|
Rendered dashboard response using the registered selector providers. |
Source code in src/codex_django/cabinet/views/dashboard.py
10 11 12 13 14 15 16 17 18 19 20 21 | |
Site settings views
codex_django.cabinet.views.site_settings
Views for cabinet site-settings pages and HTMX partials.
Functions
site_settings_view(request)
Отображает единую страницу всех настроек сайта и обрабатывает сохранение.
Source code in src/codex_django/cabinet/views/site_settings.py
11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
site_settings_tab_view(request, tab_slug)
Устаревшая вьюха для вкладок, теперь просто редиректит на общий корень по якорю.
Source code in src/codex_django/cabinet/views/site_settings.py
27 28 29 30 | |