Menu & Navigation Configuration
Developer guide for the Enezaframework. Part of the Developer documentation.
Table of Contents
- Overview
- App Config Attributes
- The
menusStructure - Menu Item Reference
- Icons with
load_icon - Complete Example
- Change History
- Related Guides
Overview
An app declares its presence in the ERP navigation through a menus list on its AppConfig in
apps.py. Two context processors read those lists and render the navigation:
sidebar_menu exposes all_app_menus / current_app_menu, and module_menu builds the top-level
module list from each app's menu_verbose_name, app_entry_menu, app_icon, and menu_position.
flowchart TD
APPCFG[AppConfig.menus]
APPCFG --> FT1[fasttab: ap_masterdata]
APPCFG --> FT2[fasttab: ap_setup]
FT1 --> MI1[menuitem: Vendors]
FT2 --> MI2[menuitem: Vendor Posting Groups]
FT2 --> MI3[menuitem: Vendor Groups]
FT2 --> MI4[menuitem: Vendor Price Groups]
FT2 --> MI5[menuitem: Vendor Branches]Menus are declared in
apps.pyon theAppConfigclass. There is noapp.pyfile involved.
App Config Attributes
Beyond menus, an AppConfig can carry top-level menu metadata:
| Attribute | Type | Description |
|---|---|---|
name |
str | The Django app name, for example accountpayable. |
menu_verbose_name |
str | Human-readable app name shown in the top-level navigation. |
app_entry_menu |
str | Default landing URL name, for example myapp:myapp_dashboard. The module menu prefers the dashboard entry for the app label. |
app_icon |
str | Icon key for the app entry. |
menu_position |
int | Ordering hint for the app within the top-level menu (defaults to 99). |
menus |
list | The fast tabs and their menu items. |
module_menu only includes apps that define all three of menu_verbose_name, app_icon, and
app_entry_menu, then sorts them by menu_position.
Always call super().ready() if you override ready() and import app signals there.
Dashboard-first menu entries
A CLI-generated app starts with menus = [] and an app_entry_menu placeholder. The app still appears in the module menu because it defines menu_verbose_name, app_icon and app_entry_menu.
The module menu resolves the real entry URL to the dashboard app:
/dashboards/<app_label>/
If the module has no dashboard definition yet, Enezadashboard renders its empty state. This is the intended first screen for a fresh app; no sample dashboard view or sample menu items are generated.
Add fast tabs and menu items only after real views exist. If a project removes enezadashboard from ENEZA_APPS, set app_entry_menu to a real URL or omit the menu attributes.
The menus Structure
menus is a Python list of fast-tab dictionaries.
from django.apps import AppConfig
from enezaframework.utils import load_icon
name = "accountpayable"
class AccountpayableConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "accountpayable"
menu_verbose_name = "Accounts Payable"
app_entry_menu = "accountpayable:vendortable_list"
app_icon = "users_icon"
menu_position = 30
def ready(self):
import accountpayable.signals # noqa: F401
menus = [
{
"fasttab": "ap_masterdata",
"name": "AP Master Data",
"icon": load_icon("users_icon"),
"menuitems": [
{
"url": f"{name}:vendortable_list",
"name": "Vendors",
"icon": load_icon("vendor_icon"),
},
],
},
{
"fasttab": "ap_setup",
"name": "AP Setup",
"icon": load_icon("settings_icon"),
"menuitems": [
{
"url": f"{name}:vendorpostinggroup_list",
"name": "Vendor Posting Groups",
"icon": load_icon("posting_group_icon"),
},
{
"url": f"{name}:vendorgroup_list",
"name": "Vendor Groups",
"icon": load_icon("group_icon"),
},
],
},
]
f"{name}:vendortable_list"buildsaccountpayable:vendortable_list. Theurlvalue is a Django URL name (app_name:url_name), not a filesystem path. See URL Auto-Registration for how those names are generated.
Menu Item Reference
Fast tab (top-level dictionary)
| Key | Type | Required | Description |
|---|---|---|---|
fasttab |
str | Yes | Unique key identifying the group of related menu items. |
name |
str | Yes | Display name of the fast tab. |
icon |
str | Yes | Icon for the fast tab, via load_icon(...). |
menuitems |
list | Yes | The individual links shown under the fast tab. |
Menu item
| Key | Type | Required | Description |
|---|---|---|---|
url |
str | Yes | Django URL name in app_name:url_name form. |
name |
str | Yes | Display name of the link. |
icon |
str | Yes | Icon for the link, via load_icon(...). |
For framework-generated CRUD views, the URL name is derived from the model or url_name, using the
suffixes documented in URL Auto-Registration — commonly _list, _detail,
_create, and _delete.
Icons with load_icon
load_icon reads an SVG and returns it marked safe for inline rendering.
from enezaframework.utils import load_icon
icon = load_icon("settings_icon") # 24x24 default
big = load_icon("settings_icon", 32, 32) # custom size
Signature: load_icon(name, width=24, height=24).
The function resolves finders.find(f"icons/{name}.svg"), so icons live in a static icons/ folder (for
example static/icons/), not static/assets/icons/. If the icon cannot be found, load_icon
returns a fallback placeholder SVG — verify the SVG exists and that the static files app is configured.
Complete Example
from django.apps import AppConfig
from enezaframework.utils import load_icon
class CrmConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "crm"
menus = [
{
"fasttab": "common_setup",
"name": "Common Setup",
"icon": load_icon("settings_icon"),
"menuitems": [
{
"url": "crm:country_list",
"name": "Countries",
"icon": load_icon("flag_icon"),
},
{
"url": "crm:custtable_list",
"name": "Customers",
"icon": load_icon("handshake"),
},
],
},
]
The user is solely responsible for testing and validating navigation; the developer/agent does not run the application.
Change History
Dated changes that affect this guide, taken from
docs/Release note/CHANGELOG.md and the release notes. For the
complete history, see the changelog.
| Date | Version | What changed |
|---|---|---|
| 2026-08-23 | 0.2.19 | Sidebar menu state persistence: the active fasttab per app is stored in localStorage, and the section containing the active page auto-opens on first visit. |
| 2026-10-31 | 0.2.22 | CLI-scaffolded apps keep app_entry_menu for the module menu but start with menus = []; the dashboard entry renders its empty state until a dashboard is designed. |
The menus list structure and the app-level metadata attributes have no other dated changes in the
0.2.7–0.2.19 window.