Contents Menu Expand Light mode Dark mode Auto light/dark, in light mode Auto light/dark, in dark mode Skip to content
iommi 7.14.3 documentation
Logo
iommi 7.14.3 documentation
  • Getting started
  • Tutorial
  • Common config
    • after
    • assets
    • attr
    • attrs
    • auto
    • endpoints
    • extra and extra_evaluated
    • extra_params
    • include
    • iommi_style
    • name/display_name/iommi_path
    • tag
    • template
    • title/h_tag
  • Components
    • Edit tables
    • Forms
    • Fragments
    • Main menu
    • Pages
    • Queries
    • Tables
  • Cookbook
    • General
    • Parts & Pages
    • Forms
    • Tables
    • Edit tables
    • Queries
    • Porting
    • Main menu
  • Understanding iommi
    • Architecture
    • Equivalence
    • Philosophy
    • Registrations
    • Semantic models
  • Access control
  • Admin
  • API Reference
    • Action
    • Asset
    • Attrs
    • Cell
    • Cells
    • Column
    • ColumnHeader
    • Container
    • EditColumn
    • EditTable
    • Endpoint
    • Field
    • Filter
    • Form
    • FormAutoConfig
    • Fragment
    • Header
    • HeaderConfig
    • Members
    • Menu
    • MenuItem
    • Page
    • Part
    • Query
    • QueryAutoConfig
    • Style
    • Table
    • TableAutoConfig
    • Traversable
  • Dev tools
  • Add iommi to a FBV
  • Path decoding
  • Production use
  • Registrations
  • Style
  • Views
  • Imports used in the iommi documentation
  • Changelog
  • Credits
  • Contributing
  • @github
  • @discord
  • @pypi
Back to top
View this page

Main menu¶

How do I control which menu items are shown for a user?¶

Using include you can control which menu items are shown for a given user. This also controls access, so you can know that your menu and your access control are always in sync.

menu = MainMenu(
    items=dict(
        albums=M(
            view=albums_view,
        ),
        artists=M(
            view=artists_view,
            include=lambda user, **_: user.is_staff,
        ),
    ),
)
▼ Hide result
▼ Hide result

How do I control the display name of a menu item?¶

By default the display name is derived from the name of the M object. So given:

menu = MainMenu(
    items=dict(
        albums=M(view=albums_view),
    ),
)
▼ Hide result

The name would be “albums”, and the display name is automatically derived as “Albums”. The translation from name to display_name replaces _ with space, runs gettext_lazy() on the result, and then capitalizes that.

If you want to do something else, pass the display_name parameter:

menu = MainMenu(
    items=dict(
        albums=M(
            view=albums_view,
            display_name=gettext_lazy('Discography'),
        ),
    ),
)
▼ Hide result

Note that display_name can be a function too.

How do I add sub-paths for a menu item?¶

Since the menu system can control access, it is useful to nest path mappings under a specific menu item without showing them in the menu. This is done with the paths argument:

menu = MainMenu(
    items=dict(
        albums=M(
            view=albums_view,
            paths=[
                path('<album_pk>/edit/', edit_album_view),
            ],
        ),
    ),
)
► Show result

How do I add external links in the menu?¶

Use the special value EXTERNAL for the view argument, and use url argument:

menu = MainMenu(
    items=dict(
        albums=M(
            view=EXTERNAL,
            url='https://docs.iommi.rocks',
        ),
    ),
)
▼ Hide result

Note the icon added by default for an external link. This is configurable via the icon_formatter on your Style.

How do I nest menu items?¶

You can create a menu hierarchy with the items argument, which produces expandable sections. iommi will open the menu items that matches the current URL by default. You can also force a submenu to be open with the open argument:

menu = MainMenu(
    items=dict(
        things=M(
            view=things_view,
            open=True,  # force open
            items=dict(
                albums=M(
                    view=albums_view,
                ),
                artists=M(
                    view=artists_view,
                )
            ),
        ),
    ),
)
▼ Hide result

The open argument can be a callable.

How do I put arbitrary html in the menu?¶

With the template argument you can put arbitrary html into menu items:

menu = MainMenu(
    items=dict(
        albums=M(
            view=EXTERNAL,
            template=Template('''
            <li style="margin-left: 1rem">
                <span style="display: inline-block; width: 1.5rem; background: red; border-radius: 50%">&nbsp;</span>
                <span style="display: inline-block; width: 1.5rem; background: orange; border-radius: 50%">&nbsp;</span>
                <span style="display: inline-block; width: 1.5rem; background: yellow; border-radius: 50%">&nbsp;</span>
                <span style="display: inline-block; width: 1.5rem; background: green; border-radius: 50%">&nbsp;</span>
                <span style="display: inline-block; width: 1.5rem; background: blue; border-radius: 50%">&nbsp;</span>
            </li>
            ''')
        ),
    ),
)
▼ Hide result

Note that you want to include the <li> tag.

You can also override the base template via your Style.

How do I show which specific object I am on in the menu?¶

If you have a list of objects and you click into one of them, you might want to show that item in the menu, and potentially also sub-pages for that item. You do that by using iommi path decoders, and mapping everything together with display_name, path, params and url:

menu = MainMenu(
    items=dict(
        albums=M(
            view=albums_view,
            items=dict(
                album=M(
                    view=album_view,
                    display_name=lambda album, **_: str(album),
                    path='<album_pk>/',
                    params={'album'},
                    url=lambda album, **_: f'/albums/{album.pk}/',
                ),
            )
        ),
    ),
)
▼ Hide result

How do I make a data driven dynamic submenu?¶

There can be cases where you want a dynamic submenu where the items come from the database. To do this, specify items as a callable. Note that urls here can’t be mapped to paths, as paths need to be known at startup.

menu = MainMenu(
    items=dict(
        albums=M(
            view=albums_view,
            items=lambda **_: {
                f'album_{album.pk}': M(
                    view=EXTERNAL,
                    display_name=str(album),
                    url=album.get_absolute_url(),
                )
                for album in Album.objects.all()
            }
        )
    ),
)
▼ Hide result
Next
Understanding iommi
Previous
Porting
Copyright © 2025, Anders Hovmöller & Johan Lübcke
Made with Sphinx and @pradyunsg's Furo
On this page
  • Main menu
    • How do I control which menu items are shown for a user?
    • How do I control the display name of a menu item?
    • How do I add sub-paths for a menu item?
    • How do I add external links in the menu?
    • How do I nest menu items?
    • How do I put arbitrary html in the menu?
    • How do I show which specific object I am on in the menu?
    • How do I make a data driven dynamic submenu?