Menu & Navigation Configuration

Developer guide for the Enezaframework. Part of the architecture series.

Table of Contents

  1. Overview
  2. App Config Attributes
  3. The menus Structure
  4. Menu Item Reference
  5. Icons with load_icon
  6. Complete Example
  7. Related Guides

Overview

An app declares its presence in the ERP navigation through a menus list on its AppConfig in apps.py. The main template reads those lists and renders the navigation links, grouped into fast tabs.

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]

App Config Attributes

Beyond menus, a 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 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 for the app entry, loaded with load_icon(...).
menu_position int Ordering hint for the app within the top-level menu.
menus list The fast tabs and their menu items.

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:

text
/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.

python
from django.apps import AppConfig
from enezaframework.utils import load_icon


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 = load_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" builds accountpayable:vendortable_list. The url value is a Django URL name (app_name:url_name), not a filesystem path. See URL Auto-Registration for how those names are generated.


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.
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.

python
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 an empty/safe value and the icon simply does not render — verify the SVG exists and that the static files app is configured.


Complete Example

python
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": f"{name}:country_list",
                    "name": "Countries",
                    "icon": load_icon("flag_icon"),
                },
                {
                    "url": f"{name}:custtable_list",
                    "name": "Customers",
                    "icon": load_icon("handshake"),
                },
            ],
        },
    ]