Skip to content

Conversation

@adionit7
Copy link
Contributor

Fixes #21173: Fix plugin menu registration order timing issue

Summary

This PR fixes an issue where plugin menus registered later in the Django app initialization process were not appearing in the NetBox navigation sidebar. The problem occurred because the MENUS list was built at module import time, before all plugins had completed their ready() methods.

Problem

When multiple plugins register menus via navigation.py and PluginConfig.ready(), only the first few plugins' menus would appear in the navigation sidebar. The missing menus were properly registered in the plugin registry, but were not included in the final MENUS list.

Root Cause:

  • netbox/navigation/menu.py was imported during Django startup (in settings.py)
  • At import time, the MENUS list was built by iterating over registry['plugins']['menus']
  • However, only the first few plugins had completed their ready() methods at that point
  • Later plugins' menus were registered after MENUS was already built, so they were excluded

Solution

Converted the static MENUS list to a dynamic get_menus() function that builds the menu list on-demand at request time (when the navigation template tag is rendered). This ensures all plugins have completed their ready() methods before the menus are assembled.

Changes Made:

  • Replaced static MENUS list with get_menus() function in netbox/navigation/menu.py
  • Updated netbox/utilities/templatetags/navigation.py to call get_menus() instead of importing MENUS
  • Function builds the same menu structure, just dynamically at request time

Impact

  • Fixed: All plugin menus now appear in the navigation sidebar regardless of plugin load order
  • Backward Compatible: No changes to plugin registration API or menu structure
  • Performance: Negligible impact - building menu list is microseconds per request
  • No Breaking Changes: Function returns the same list structure as before

Testing

  • Verified that all plugin menus appear in navigation sidebar
  • Confirmed existing plugin menu registration continues to work
  • No changes required to plugin code - existing plugins work without modification

…ng issue

- Converted static MENUS list to dynamic get_menus() function
- Ensures plugin menus are built at request time after all plugins complete ready()
- Fixes issue where only first few plugin menus appeared in navigation sidebar
- Updated navigation template tag to call get_menus() dynamically
- Add missing blank line before get_menus() function definition
- Remove trailing whitespace
@pheus pheus requested review from a team and arthanson and removed request for a team January 21, 2026 18:11
Copy link
Collaborator

@arthanson arthanson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good - just checking if you looked at using a cache for this, something like:?

from functools import cache
 @cache
 def get_menus():

It's only loaded once per request, but might be easy to shave off a bit of processing each time as it shouldn't ever change without a Django restart.

Per reviewer feedback, the menu list is now cached since it doesn't change
without a Django restart. This eliminates redundant list building on each request.
@adionit7
Copy link
Contributor Author

This looks good - just checking if you looked at using a cache for this, something like:?

from functools import cache
 @cache
 def get_menus():

It's only loaded once per request, but might be easy to shave off a bit of processing each time as it shouldn't ever change without a Django restart.

Thanks for the suggestion @arthanson! Great catch.

I've added the @cache decorator from functools to cache the result. Since the menu structure doesn't change without a Django restart, this eliminates redundant list building on each request.

Changes made:

  • Added from functools import cache import
  • Applied @cache decorator to get_menus()
  • Updated docstring to document the caching behavior

@adionit7 adionit7 requested a review from arthanson January 22, 2026 21:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Plugin Menu Registration Order

2 participants