Dashboard Reference
Complete configuration reference for the Enezaframework dashboard system. Part of the Dashboards series.
Table of Contents
- A. Report Class Attributes
- B. Identifiers and Permissions
- C. Eligibility Rules
- D. Report Metadata Contract
- E. Definition Schema
- F. Widget Configuration
- G. Layout and Widget Limits
- H. Parameters, Filters, and Periods
- I. Settings
- J. Routes
- K. Error Codes
- Related Guides
A. Report Class Attributes
These attributes are declared on a report class. The base defaults come from the metadata
layer in enezareporting/report_types.py and the
unified bases in enezareporting/report_base.py.
Core report attributes
| Attribute | Type | Default | Purpose |
|---|---|---|---|
report_model |
model class | None |
Model the report reads. Required for a dashboard source unless get_report_model() resolves one. |
columns |
list | [] |
Field names, computation fields, and callables to expose. Drives dimensions, measures, tables, and previews. |
group_by |
str or tuple | "" |
Field(s) used for grouping. Grouped fields must also be in columns to be widget dimensions. |
date_field |
str | "" |
Date field used for date-range filtering and dashboard periods. |
parameter_spec |
ParameterSet |
empty | Declares the report's filter form fields. |
report_generator_class |
class | ReportGenerator |
Generator used by the view. frameworkapp uses ListViewReportGenerator. |
report_name |
str | "" |
Human title. Dashboard title falls back to report_title, then the class name. |
report_title |
str | "" |
Page title; used as a dashboard title fallback. |
report_slug |
str | "" |
Stable slug. Defaults to the lowercased class name. |
report_app_label |
str | "" |
App-label fallback. Avoid setting it when report_model exists: get_dashboard_code() prefers it, while discovery's meta.app_label prefers the model, which can split the URL/report code from the permission code. |
queryset |
queryset | None |
Optional base queryset. |
limit_records |
int | None |
Optional row cap on the report itself. |
default_order_by |
str | "" |
Default report ordering. |
swap_sign |
bool | False |
Report-specific debit/credit sign handling. |
context_variables |
list | [] |
Designer/context variables; not used by dashboard execution. |
Dashboard opt-in attributes
| Attribute | Type | Default | Purpose |
|---|---|---|---|
dashboard_enabled |
bool | False |
Required opt-in. Without it the report is never a data source. |
dashboard_code |
str | "" |
Overrides the stable report_ref. Does not change the output permission. |
report_url_name |
str | "" |
URL name used by the widget's View report link. |
dashboard_entity_scoped |
bool | False |
Calls queryset.for_entity(request=request) when the entity and method exist. |
use_query_builder |
bool | False |
Enables dashboard query-builder filter metadata. |
use_modal_filter |
bool | False |
Report-page UI behavior; not used by dashboards. |
Class methods
| Method | Returns | Notes |
|---|---|---|
get_dashboard_code() |
str | dashboard_code, or <app_label>.<slug>. |
get_dashboard_title() |
str | report_name, report_title, or class name. |
get_dashboard_url_name() |
str | report_url_name or empty. |
get_report_model() |
model class | Optional override for report_model. |
Computation fields
from django.db.models import Sum
from enezareporting.fields import ComputationField
TotalValue = ComputationField.create(
Sum,
"value",
verbose_name="Total Value",
)
- The generated column name is
<method>__<field>when nonameis supplied, for examplesum__value(enezareporting/fields.py:76-99). - A computation field becomes a measure with one supported aggregation: the
method name (
enezareporting/dashboard.py:238-278). - The class attribute (
TotalValue) is exposed as an alias, but canonical column names are safer in definitions.
B. Identifiers and Permissions
Code derivation
From enezareporting/dashboard.py and enezareporting/report_types.py:
# get_dashboard_code()
code_app_label = report_app_label
or report_model._meta.app_label
or report_class.__module__.split(".")[0]
# discovery metadata
meta_app_label = report_model._meta.app_label
or report_app_label
or report_class.__module__.split(".")[0]
report_slug = get_report_slug()
or report_slug
or report_class.__name__.lower()
report_ref = dashboard_code or f"{code_app_label}.{report_slug}"
output_code = f"output.{meta_app_label}.{report_slug}.view"
Consequences:
- Do not set
report_app_labelwhenreport_modelexists. The two app labels above can disagree, producing areport_refthat does not match the permission code. dashboard_codechangesreport_refonly. The RBAC permission still followsreport_slug.- Duplicate
report_refvalues raiseImproperlyConfiguredduring discovery (enezareporting/dashboard.py:345-353). report_urlisreverse(report_url_name). An unreversible name leaves the URL blank but does not make the report ineligible (enezareporting/dashboard.py:197-202).
Permission
Every widget execution calls:
has_output_permission(user, source.meta.output_code, request=request)
If the permission is missing, the widget returns a report_forbidden error and
the report is removed from the page's filter groups
(enezareporting/dashboard.py:501-527,
enezadashboard/services/renderer.py:156-180).
Run python manage.py rbac_sync after adding or renaming reports.
C. Eligibility Rules
A source is returned by discovery only if all conditions pass
(enezareporting/dashboard.py:204-217,
enezareporting/dashboard.py:332-355).
| Condition | Required state |
|---|---|
| Concrete report class | Not __abstract__, name does not start with _. |
| Registered | Imported at startup and present in report_type_registry. |
| Opted in | dashboard_enabled = True. |
| Supported type | TabularReportView / SummaryReportView / DetailedReportView, not crosstab, time-series, document, or drill-down. |
| Resolvable model | report_model or get_report_model() returns a model. |
| Parseable columns | check_columns(...) completes without raising. |
| Unique code | No other report produces the same report_ref. |
| User permission | output.<app_label>.<report_slug>.view granted, when listing for a user. |
Ineligible reports are excluded silently. The internal reason string is stored on the source metadata but never shown in discovery results.
D. Report Metadata Contract
DashboardReportMeta.to_dict() returns these keys
(enezareporting/dashboard.py:50-90):
| Key | Type | Contents |
|---|---|---|
code |
str | Stable report_ref. |
title |
str | Display title. |
description |
str | Report description. |
app_label |
str | Owning app label. |
report_type |
str | "tabular" for dashboard-supported reports. |
model_label |
str | "<app_label>.<model_name>". |
output_code |
str | RBAC permission code. |
report_url_name |
str | URL name, possibly empty. |
report_url |
str | Reversed URL, possibly empty. |
columns |
list | Column descriptors. |
dimensions |
list[str] | Database column names usable as categories/series. |
measures |
list | Numeric/computation descriptors. |
parameters |
list | Serialized report parameters. |
filter_fields |
list[str] | Allowed query-builder field IDs. |
filter_schema |
dict | Raw filter schema keyed by model. |
eligible |
bool | Eligibility state. |
ineligible_reason |
str | Why the report is ineligible, when applicable. |
Column descriptor
| Key | Meaning |
|---|---|
name |
Canonical column name. Use this in widget config. |
label |
Human label from verbose_name. |
type |
Django internal field type for database columns, or the computation field's declared type (number by default). |
format |
Report formatting hint. |
align |
left, right, or the generator's alignment. |
is_summable |
Whether the report marks it summable. |
is_computation |
True for computation fields. |
computation_field |
Underlying model field for computation fields. |
aggregations |
Supported aggregation names. |
aliases |
Canonical name, computation name, and unique class attribute alias. |
source |
database or magic_field. |
Measure descriptor
| Key | Meaning |
|---|---|
name |
Canonical column name. |
label |
Human label. |
aggregations |
Supported aggregation names. |
aliases |
Accepted aliases. |
Numeric database fields support sum, avg, min, max, count.
Computation fields support their own method name only.
Abridged example
The exact values depend on the report class; the shape is:
{
"code": "frameworkapp.frameworktestdocumentsales",
"title": "Framework Test Document Sales",
"app_label": "frameworkapp",
"report_type": "tabular",
"model_label": "frameworkapp.frameworktestdocumentline",
"output_code": "output.frameworkapp.frameworktestdocumentsales.view",
"report_url_name": "frameworkapp:frameworktestreport",
"report_url": "/frameworkapp/frameworktestreport/",
"columns": [
{
"name": "sum__item_quantity",
"label": "Total Quantity",
"type": "number",
"format": "number",
"align": "right",
"is_computation": true,
"computation_field": "item_quantity",
"aggregations": ["sum"],
"aliases": ["sum__item_quantity", "SumItemQuantity"],
"source": "magic_field"
}
],
"dimensions": ["item_code", "item_description"],
"measures": [
{
"name": "sum__item_quantity",
"label": "Total Quantity",
"aggregations": ["sum"],
"aliases": ["sum__item_quantity", "SumItemQuantity"]
}
],
"parameters": [
{
"name": "date_range",
"label": "Date Range",
"type": "date_range",
"required": false,
"start_field": "created_at",
"end_field": "created_at",
"form_fields": ["start_date", "end_date"]
}
],
"filter_fields": ["item_code", "item_description"],
"filter_schema": {},
"eligible": true,
"ineligible_reason": ""
}
Use the metadata endpoint to inspect the real values:
/dashboards/manage/report-meta/?report=frameworkapp.frameworktestdocumentsales
E. Definition Schema
Dashboard definition
| Key | Required | Default | Notes |
|---|---|---|---|
module |
Yes | — | Installed app label. Filled from an AppConfig source when omitted. |
code |
Yes | — | Valid slug, unique with module. |
name |
Yes | — | Display name. |
description |
No | "" |
Long description. |
is_active |
No | True |
Visibility. |
is_default |
No | False |
One active default per module. |
sort_order |
No | 0 |
Ordering. |
managed_by |
No | "seed" |
seed or admin. |
layout_template |
No | "" |
Known wireframe code; provenance only. |
default_report_ref |
No | "" |
Eligible report code. |
access_code |
No | "" |
Optional RBAC permission. |
seed_revision |
No | "" |
Stored marker. |
publish |
No | New: true |
Publish after seeding. |
tabs |
No | [] |
Tab definitions. |
data_settings |
— | — | Not read by seeding. Use the designer. |
Tab definition
| Key | Required | Default | Notes |
|---|---|---|---|
code |
Yes | — | Unique within the version. |
name |
Yes | — | Display name. |
description |
No | "" |
Description. |
icon |
No | "" |
Must be in TAB_ICON_KEYS for seeded definitions; the designer offers only those choices. |
sort_order |
No | 0 |
Ordering. |
layout |
No | {} |
Stored layout metadata. |
filter_config |
No | {} |
date_range, data, parameter_defaults. |
widgets |
No | [] |
Widget definitions. |
Widget definition
| Key | Required | Default | Notes |
|---|---|---|---|
code |
Yes | — | Unique within the tab. |
title |
Yes | — | Display title. |
type / widget_type |
Yes | — | kpi, chart, table, report_preview. |
report_ref |
Yes | — | Eligible data source. |
description |
No | "" |
Supporting text. |
display_config |
No | {} |
Type-specific configuration. |
layout |
No | By type | x, y, w, h. |
parameter_config |
No | {} |
Allowed report parameter values. |
filter_config |
No | {} |
Query-builder rules. |
sort_order |
No | 0 |
Ordering. |
is_active |
No | True |
Inactive widgets are skipped. |
Unknown keys are ignored by the seeder. They do not raise an error, so a typo in
an optional key can silently do nothing. Validate with --dry-run and inspect
the resulting draft.
F. Widget Configuration
All widget keys live under display_config. Validation code:
KPI
| Key | Type | Default | Rules |
|---|---|---|---|
measure |
str | "" |
Must be a report column/alias. Required unless aggregation is count. For numeric results it should be a measure. |
aggregation |
str | auto | sum, avg, min, max, count, or empty. When the measure descriptor is found, the value must be one of its aggregations. |
format |
str | number |
number, currency, percent, integer, text, or empty. |
decimals |
int | 0 |
0–6. |
prefix |
str | "" |
Prepended to the formatted value. |
suffix |
str | "" |
Appended to the formatted value. |
sparkline |
object | none | {category_field, value_field, limit}. Limit 2–60, default 24. Both fields must exist on the report. |
percent_is_fraction |
bool | true |
Definition-only. When true, percent values are multiplied by 100. |
Behavior:
- Formatting is done by
format_metric()(enezadashboard/widgets/base.py:61-81). integerandtextuse the same numeric formatting path asnumber; they do not coerce values to strings.currencydoes not imply two decimals. Setdecimals: 2explicitly; the form default is0.- The KPI compares against the previous period or previous year automatically when the page has comparison enabled and the report supports dates.
- A sparkline runs a query over the report rows and renders an SVG; it is not a client-side chart.
Chart
| Key | Type | Default | Rules |
|---|---|---|---|
chart_type |
str | bar |
One of the 16 types below. |
category_field |
str | "" |
Required except for gauge. Must be a report column/alias. Numeric for scatter and bubble. |
value_field |
str | "" |
Required except for gauge. Must be a numeric measure. |
series_field |
str | "" |
Required for heatmap, stacked_bar, stacked_area. Must be a column. |
line_field |
str | "" |
Required for combo. Must be a numeric measure. |
size_field |
str | "" |
Required for bubble. Must be a numeric measure. |
comparison_field |
str | "" |
Optional. Used by line, area, combo, and radar; when set, must be a numeric measure. |
measure |
str | "" |
Gauge only. Alternative to value_field. Must be a numeric measure. |
aggregation |
str | sum |
Gauge only. sum, avg, min, max, or count. |
target |
number | none | Target line for line/area, or target value for gauge/bullet. Numeric. |
scale_max |
number | none | Gauge/bullet maximum. Numeric and greater than zero. |
limit |
int | 20 |
1–MAX_CHART_CATEGORIES (default 100). |
sort |
str | none | none, asc, or desc. |
colors |
list[str] | palette | Hex colors. Definition-only. |
show_legend |
bool | Type-dependent | Defaults on for donut, pie, stacked, combo, radar, line, area. |
width |
int | 640 |
SVG width. Definition-only. |
height |
int | 240 |
SVG height. Definition-only. |
fill |
bool | false |
Fill a line chart; area is always filled. Definition-only. |
zero |
bool | true |
Include zero in line/area/combo scales. Definition-only. |
comparison_label |
str | field name | Legend label for a comparison field. Definition-only. |
comparison_color |
str | faint | Legend color for a comparison field. Definition-only. |
Chart types:
line, area, bar, horizontal_bar, donut, pie, funnel, gauge,
heatmap, radar, scatter, bubble, bullet, combo, stacked_bar,
stacked_area (enezadashboard/widgets/chart.py:27-44).
Requirement matrix:
| Type | Category | Value | Series | Line | Size | Measure/aggregation | Target/scale |
|---|---|---|---|---|---|---|---|
bar |
Yes | Yes | — | — | — | — | — |
horizontal_bar |
Yes | Yes | — | — | — | — | — |
line |
Yes | Yes | — | — | — | — | — |
area |
Yes | Yes | — | — | — | — | — |
donut |
Yes | Yes | — | — | — | — | — |
pie |
Yes | Yes | — | — | — | — | — |
funnel |
Yes | Yes | — | — | — | — | — |
radar |
Yes | Yes | — | — | — | — | — |
heatmap |
Yes | Yes | Yes | — | — | — | — |
stacked_bar |
Yes | Yes | Yes | — | — | — | — |
stacked_area |
Yes | Yes | Yes | — | — | — | — |
scatter |
Yes (numeric) | Yes | — | — | — | — | — |
bubble |
Yes (numeric) | Yes | — | — | Yes | — | — |
bullet |
Yes | Yes | — | — | — | — | Optional |
combo |
Yes | Yes | — | Yes | — | — | — |
gauge |
— | — | — | — | — | Yes | Optional |
Runtime rules:
- Pie, donut, funnel, stacked bar, stacked area, and heatmap reject negative
values with
invalid_data(enezadashboard/widgets/chart.py:245-253). - Charts render server-side; no JavaScript chart library is loaded.
gaugeuses a true aggregate, not report rows.
Table
| Key | Type | Default | Rules |
|---|---|---|---|
columns |
list[str] | First 6 report columns | Each must be a report column/alias. |
page_size |
int | 20 |
1–MAX_PAGE_SIZE (default 100). |
sortable |
bool | true |
Enables sortable headers. |
dense |
bool | false |
Compact row rendering. |
show_header |
bool | true |
Show the table header. |
Runtime query parameters: page, page_size, sort, dir. page_size is
clamped to MAX_PAGE_SIZE (enezadashboard/widgets/table.py:45-111).
Report preview
| Key | Type | Default | Rules |
|---|---|---|---|
columns |
list[str] | First 6 report columns | Each must be a report column/alias. |
row_limit |
int | 5 |
1–MAX_PREVIEW_ROWS (default 20). |
show_header |
bool | true |
Show the header. |
A preview is a non-paginated table with page_size = row_limit. It reuses the
table renderer, so sortable defaults to true internally, but the preview form
does not expose a sortable toggle
(enezadashboard/widgets/report_preview.py:30-43).
G. Layout and Widget Limits
| Limit | Value | Source |
|---|---|---|
| Grid columns | 12 | enezadashboard/services/validation.py:44-49 |
x |
Non-negative; x + w <= 12 |
Same |
y |
Non-negative; canvas endpoint caps at 200 | enezadashboard/views/designer.py:645-654 |
w |
2–12 | Same |
h |
2–8 | Same |
| Chart categories | MAX_CHART_CATEGORIES (100) |
enezadashboard/widgets/chart.py:139-145 |
| Table page size | MAX_PAGE_SIZE (100) |
enezadashboard/widgets/table.py:23-29 |
| Preview rows | MAX_PREVIEW_ROWS (20) |
enezadashboard/widgets/report_preview.py:22-28 |
| Dashboard data limit | 1–1,000,000 (form) | enezadashboard/forms.py:116-125 |
Default widget layout by type when a definition omits layout
(enezadashboard/services/seeding.py:84-91):
| Type | Default x, y, w, h |
|---|---|
kpi |
0, 0, 3, 2 |
chart |
0, 0, 6, 4 |
report_preview |
0, 0, 6, 4 |
table |
0, 0, 12, 4 |
H. Parameters, Filters, and Periods
Allowed widget parameters
parameter_config may contain only:
start_date,end_datefor aDateRangeParam;- the parameter
nameand anyform_fieldsfor every other parameter.
Unknown keys fail validation with “Unknown report parameter(s)”.
Widget filter shape
{
"condition": "AND",
"primary_model": "frameworkapp.frameworktestdocumentline",
"related_models": [],
"groups": [
{
"condition": "AND",
"rules": [
{
"id": "item_code",
"field": "item_code",
"type": "string",
"input": "text",
"operator": "equal",
"value": "A-100"
}
]
}
]
}
Rules:
- Each rule
idmust be inmeta.filter_fields. operatormust be supported by the workflow engine.- Page-level user filters may use
AND,OR, orNOTgroup conditions;NOTrequires exactly one rule (enezadashboard/services/renderer.py:635-668). - Widget-level admin filters and page-level user filters merge with
ANDwhen the admin filter is alsoAND. An admin filter usingORis not merged, and the page shows a warning (enezadashboard/services/renderer.py:322-332,enezadashboard/services/renderer.py:733-758).
Dashboard and tab date settings
| Key | Location | Meaning |
|---|---|---|
date_range.enabled |
Tab filter_config |
Enables the tab's date defaults. |
date_range.default_period |
Tab filter_config |
Preset or custom. |
date_range.default_start_date |
Tab filter_config |
ISO date; used with custom. |
date_range.default_end_date |
Tab filter_config |
ISO date; used with custom. |
data.reference_date_field |
Tab filter_config |
Tab-level reference date override. |
data.limit |
Tab filter_config |
Tab-level row cap. |
parameter_defaults |
Tab filter_config |
Values applied to every widget before widget params. |
data_settings.reference_date_field |
Dashboard | Dashboard reference date. |
data_settings.limit |
Dashboard | Dashboard row cap. |
data_settings.default_period |
Dashboard | Dashboard default period. |
Period resolution order:
- tab
date_range.default_period(defaultmeans no range; a preset orcustomresolves dates) - tab
date_range.default_start_date/default_end_date(when the period iscustom) - dashboard
data_settings.default_period - site
DEFAULT_PERIOD
Reference-date resolution order:
- tab
filter_config.data.reference_date_field - dashboard
data_settings.reference_date_field - report's
date_range.start_field - report's
date_field - common created-date fields (
created_at,created, …) - the first date field on the model
Reference-date resolution is in
enezadashboard/services/renderer.py:495-533.
Period resolution is in
enezadashboard/services/renderer.py:218-254.
Period presets
today, yesterday, last_7_days, last_30_days, this_week, last_week,
this_month, last_month, this_quarter, last_quarter, this_year,
last_year, ytd, custom
(enezadashboard/services/periods.py:10-25).
Comparison choices: none, previous, previous_year
(enezadashboard/services/periods.py:34-41).
Page query parameters
| Parameter | Meaning |
|---|---|
period |
Preset key, custom, or default. |
start_date, end_date |
Custom range, or legacy direct dates. |
compare |
none, previous, previous_year. |
filters |
JSON payload of page-level user filters, keyed by report. |
page |
Table page number. |
page_size |
Table page size. |
sort, dir |
Table sort column and direction. |
tab |
Selected tab code. |
Invalid periods fall back to the configured default and add a warning rather
than raising (enezadashboard/services/periods.py:218-260).
I. Settings
Settings are read by dashboard_settings() and merged over the defaults in
enezadashboard/conf.py:3-21:
ENEZA_DASHBOARD_SETTINGS = {
"DEFAULT_PAGE_SIZE": 20,
"MAX_PAGE_SIZE": 100,
"MAX_CHART_CATEGORIES": 100,
"MAX_PREVIEW_ROWS": 20,
"QUERY_CACHE_TTL": 0,
"QUERY_TIMEOUT_MS": 0,
"DESIGNER_ACTION_CODE": "action.enezadashboard.manage",
"AUTO_REFRESH_MIN_SECONDS": 30,
"DEFAULT_PERIOD": "last_30_days",
"DEFAULT_COMPARE": "none",
"MAX_USER_FILTER_RULES": 20,
"MAX_USER_FILTER_GROUPS": 5,
}
| Key | Default | Consumed by |
|---|---|---|
DEFAULT_PAGE_SIZE |
20 |
Table and renderer page size. |
MAX_PAGE_SIZE |
100 |
Table validation and renderer clamp. |
MAX_CHART_CATEGORIES |
100 |
Chart validation and rendering. |
MAX_PREVIEW_ROWS |
20 |
Report-preview validation. |
DEFAULT_PERIOD |
last_30_days |
Renderer default period. |
DEFAULT_COMPARE |
none |
Renderer default comparison. |
MAX_USER_FILTER_RULES |
20 |
Filter panel metadata. |
MAX_USER_FILTER_GROUPS |
5 |
Filter panel metadata. |
QUERY_CACHE_TTL |
0 |
Declared default; no cross-request TTL implementation exists. |
QUERY_TIMEOUT_MS |
0 |
Declared default; no query timeout is enforced. |
DESIGNER_ACTION_CODE |
action code | Declared default; designer enforcement currently hardcodes action.enezadashboard.manage. |
AUTO_REFRESH_MIN_SECONDS |
30 |
Declared default; no auto-refresh loop is implemented in the dashboard views. |
The project already ships the main overrides in framework/settings.py:326-335.
The remaining keys in the block above come from conf.py defaults. Override
individual keys in the project's settings rather than redefining the whole
dictionary.
J. Routes
All dashboard routes use the enezadashboard namespace.
| Name | Pattern |
|---|---|
index |
/dashboards/ |
preference |
/dashboards/preferences/ |
manage_list |
/dashboards/manage/ |
create |
/dashboards/manage/create/ |
report_meta |
/dashboards/manage/report-meta/ |
designer |
/dashboards/manage/<uuid:dashboard_id>/ |
edit |
/dashboards/manage/<uuid:dashboard_id>/edit/ |
apply_wireframe |
/dashboards/manage/<uuid:dashboard_id>/apply-wireframe/ |
clone |
/dashboards/manage/<uuid:dashboard_id>/clone/ |
deactivate |
/dashboards/manage/<uuid:dashboard_id>/deactivate/ |
unpublish |
/dashboards/manage/<uuid:dashboard_id>/unpublish/ |
publish |
/dashboards/manage/<uuid:dashboard_id>/publish/ |
take_ownership |
/dashboards/manage/<uuid:dashboard_id>/take-ownership/ |
preview |
/dashboards/manage/<uuid:dashboard_id>/preview/ |
versions |
/dashboards/manage/<uuid:dashboard_id>/versions/ |
restore_version |
/dashboards/manage/<uuid:dashboard_id>/versions/<uuid:version_id>/restore/ |
tab_create |
/dashboards/manage/<uuid:dashboard_id>/tabs/ |
tab_update |
/dashboards/manage/<uuid:dashboard_id>/tabs/<uuid:tab_id>/ |
tab_delete |
/dashboards/manage/<uuid:dashboard_id>/tabs/<uuid:tab_id>/delete/ |
widget_create |
/dashboards/manage/<uuid:dashboard_id>/tabs/<uuid:tab_id>/widgets/ |
widget_update |
/dashboards/manage/<uuid:dashboard_id>/tabs/<uuid:tab_id>/widgets/<uuid:widget_id>/ |
widget_delete |
/dashboards/manage/<uuid:dashboard_id>/tabs/<uuid:tab_id>/widgets/<uuid:widget_id>/delete/ |
widget_preview |
/dashboards/manage/<uuid:dashboard_id>/tabs/<uuid:tab_id>/widgets/<uuid:widget_id>/preview/ |
widget_layout |
/dashboards/manage/<uuid:dashboard_id>/tabs/<uuid:tab_id>/widgets/<uuid:widget_id>/layout/ |
module_dashboards |
/dashboards/<str:module>/dashboards/ |
module_entry |
/dashboards/<str:module>/ |
detail |
/dashboards/<str:module>/<slug:dashboard_code>/ |
tab |
/dashboards/<str:module>/<slug:dashboard_code>/tabs/<slug:tab_code>/ |
widget |
/dashboards/<str:module>/<slug:dashboard_code>/tabs/<slug:tab_code>/widgets/<slug:widget_code>/ |
Source: enezadashboard/urls.py:7-129.
K. Error Codes
DashboardValidationError carries message, code, and optional structured
errors (enezareporting/dashboard.py:30-47).
| Code | Raised when | Typical fix |
|---|---|---|
unknown_report |
A widget or definition references a code discovery does not know. | Check report_ref, opt-in, import, and cache. |
report_forbidden |
The user lacks the output permission or the report's access function. | Grant output.<app_label>.<report_slug>.view; run rbac_sync. |
report_not_eligible |
Execution was requested for an ineligible report. | Fix opt-in, type, model, or columns. |
invalid_config |
A widget field, type, format, limit, layout, measure, or aggregation is invalid. | Read the error message; correct display_config. |
invalid_parameters |
A parameter is unknown or fails the report form. | Use allowed parameter names and valid values. |
invalid_filter |
A filter field or operator is not allowed. | Use meta.filter_fields and supported operators. |
filters_not_supported |
A filter was supplied to a report without use_query_builder. |
Enable the report flag or remove the filter. |
filters_unavailable |
The workflow filter engine is missing or filter metadata cannot be read. | Install/configure the workflow engine. |
invalid_date_field |
A dashboard reference date is not a date field on the report model. | Choose a DateField/DateTimeField. |
unsupported_aggregate |
A KPI aggregate was requested for a custom group-by report. | Use a supported computation or numeric field. |
invalid_data |
A chart type that cannot show negatives received one. | Filter or choose another chart type. |
query_failed |
An unexpected exception occurred while rendering a widget. | Check the server log; the widget error is deliberately generic. |
no_draft |
Publishing a dashboard with no draft version. | Re-open the designer to create a draft. |
publish_invalid |
Publication validation failed. | Fix the listed tab/widget errors. |
publish_forbidden |
The publisher cannot access the dashboard's module or access_code. |
Grant module/access-code permission or publish as a permitted user. |
invalid_default |
Tried to default an unpublished or inactive dashboard. | Publish and activate it first. |
invalid_definition |
Seeding rejected a definition. | Inspect the errors list from --dry-run --json. |
default_conflict |
Another administrator-owned default exists for the module. | Use --force deliberately or change ownership. |
unknown_wireframe |
A definition or request names a wireframe that does not exist. | Use a code from the catalogue. |
Non-DashboardValidationError failures:
- Duplicate report code —
ImproperlyConfiguredduring discovery. - Duplicate definition identity —
ValueErrorduringload_definitions. - Model/slug validation — Django
ValidationErrorfrom model or form validation.