[Django]-Wagtail / Django inbuilt main menu

1👍

Have you seen https://github.com/rkhleics/wagtailmenus? It’s designed to “manage and render multi-level navigation and simple flat menus in a consistent, flexible way”.

👤tomd

2👍

I wanted to have automatically generated menu too but only first level with home. I might did something naive but it works. I am using Wagtail 2.5.1 and Django 2.2.2.

My Wagtail page structure look like this:

                                 Home page
                    /                                   \
                Blog                                   About
              /  |   \                            
      n_item   n_item  n_item 

I am using bootstrap4 so this is my nav in base.html template:

{% with root_p=request.site.root_page %}

        {# this is static item for home #}
        <ul class="navbar-nav ml-auto">
          <li class="nav-item">
                <a class="nav-link {% if '/' == request.path %} active {% endif %}" href="{{root_p.url}}">{{root_p.slug}}</a>
          </li>

        {# Here I am looping home's childrens #}
          {% for nav in root_p.get_children.live %}
              {% if nav.show_in_menus %}
                  <li class="nav-item">
                      <a class="nav-link {% if nav.slug in request.path %} active {% endif %}" href="{{nav.url}}">{{nav.slug}}</a>
                  </li>
              {% endif %}
          {% endfor %}
        </ul>

{% endwith %}

This is result:
wagtail automatically generated menu

Now I am able to change slug, tick/untick “show in menus” and my bootstrap menu reflect these changes.

EDIT:
My last answer does not solve custom order of menu items. We can order items by standard fields in Page model “first_published_at” or alphabetically by “title” name. But I needed make it custom. So I added custom integer field in each my page model. Then wagtail users can change order of menu items using “promote tab”.

My current page structure look like this:

                             Home
                /              |           \
         Case studies      Services      Contact

My page model: (example of services only)

class ServicesPage(Page):

    template = "home/services.html"
    max_count = 1     
    subpage_types = []
    menu_order = models.IntegerField(default = 0, help_text = "Setup custom menu order")

    promote_panels = Page.promote_panels + [
       FieldPanel('menu_order'),
   ]
    class Meta:
        verbose_name = "Services"
        verbose_name_plural = "Services"

This is how it looks in promote tab of each page model
enter image description here

Last step is edit navbar loop in base template:

{% with root_p=request.site.root_page %}
      {% for nav in root_p.get_children.specific.live|dictsort:"menu_order" %}
      {% if nav.show_in_menus %}
      <li class="nav-item {% if nav.slug in request.path %} active {% endif %}">
          <a class="nav-link" href="{{nav.url}}">{{nav.title}}</a>
      </li>
      {% endif %}
      {% endfor %}
{% endwith %}

For ordering I am using default django template filter dictsort.
I guess it is not best way how to do that, but it works.

Leave a comment