Extending the navigation menu

You may have noticed that while our Polls application has been integrated into the CMS, with plugins, toolbar menu items and so on, the site’s navigation menu is still only determined by django CMS Pages.

We can hook into the django CMS menu system to add our own nodes to that navigation menu.

For this we need a file called menu.py in our application. Add polls_plugin/menu.py:

  1. from django.core.urlresolvers import reverse
  2. from django.utils.translation import ugettext_lazy as _
  3. from cms.menu_bases import CMSAttachMenu
  4. from menus.base import NavigationNode
  5. from menus.menu_pool import menu_pool
  6. from polls.models import Poll
  7. class PollsMenu(CMSAttachMenu):
  8. name = _("Polls Menu") # give the menu a name this is required.
  9. def get_nodes(self, request):
  10. """
  11. This method is used to build the menu tree.
  12. """
  13. nodes = []
  14. for poll in Poll.objects.all():
  15. node = NavigationNode(
  16. title=poll.question,
  17. url=reverse('polls:detail', args=(poll.pk,)),
  18. id=poll.pk, # unique id for this node within the menu
  19. )
  20. nodes.append(node)
  21. return nodes
  22. menu_pool.register_menu(PollsMenu)

What’s happening here:

  • we define a PollsMenu class, and register it
  • we give the class a name attribute (will be displayed in admin)
  • in its get_nodes() method, we build and return a list of nodes, where:
  • first we get all the Poll objects
  • … and then create a NavigationNode object from each one
  • … and return a list of these NavigationNodes

This menu class is not active until attached to the apphook we created earlier. So open your cms_app.py and add:

  1. from polls_plugin.menu import PollsMenu

for importing PollsMenu and

menus = [PollsMenu]

to the PollsApp class.

Any page that is attached to the Polls application will now have submenu items for each of the Polls in the database.