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”.
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 %}
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
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.