Search code examples
djangodjango-cms

Active CMS Menu on apphooked object


I have an site with Django CMS 3.5.1 and Django 1.11.11 and it has a menu built with CMS. One of its pages is an apphooked list of events. When I click on an event detail, the menu loses its active class.

Here's my menu:

{% for child in children %}
    <li class="js-submenuParent {% if child.selected or child.ancestor %}active{% endif %}">
        <a href="{% if child.children %}javascript:void(0);{% else %}{{ child.attr.redirect_url|default:child.get_absolute_url }}{% endif %}" class="{% if child.children %}submenu-btn js-openSubmenu{% endif %}">{{ child.get_menu_title }}</a>

    {% if child.children %}
        <ul class="submenu js-submenu">
            {% show_menu from_level to_level extra_inactive extra_active template "" "" child %}
        </ul>
    {% endif %}
    </li>
{% endfor %}

I thought child.ancestor could solve the problem (or even child.selected as it seems I can access the parent's title using {% page_attribute "page_title" %}) but it doesn't. Do I have to make a custom apphook menu just to do that or is there a simpler solution?


Solution

  • The page you attach your application to is the last point the menu system knows about until you integrate a menu for your application.

    Adding a menu allows your app URLs to integrate with the menu app via NavigationNode(title, url, id) objects for your URLs.

    So if you've got a detail view, you could attach a simple menu;

    from menus.base import NavigationNode
    from menus.menu_pool import menu_pool
    from django.utils.translation import ugettext_lazy as _
    from cms.menu_bases import CMSAttachMenu
    
    class EventMenu(CMSAttachMenu):
    
        name = _("event menu")
    
        def get_nodes(self, request):
            nodes = []
            n = NavigationNode(_('detail page'), "/detail", 1)
            nodes.append(n)
            return nodes
    
    menu_pool.register_menu(EventMenu)
    

    The docs on this are here; http://docs.django-cms.org/en/latest/how_to/menus.html#integration-attach-menus

    Based on the above, you could also generate nodes based on lists/querysets etc like you've found with a little investigation;

    def get_nodes(self, request):
        nodes = []
        for event in Event.objects.published():
            n = NavigationNode(
                event.title,  # title
                event.get_absolute_url(),  # url
                'id_{slug}'.format(slug=event.slug),  # unique ID for node
                visible=False
            )
            nodes.append(n)
        return nodes