Reputation: 575
Started a project working with Wagtail CMS and what I understood of their principal of pages is that it is hierarchical leading me to the conclusion that pages are either parent/child related or siblings.
So how I have done it is have my main page landing and all other pages would be children of this page.
Here is my structure
Home page
/ | \
News About us Events
/ | \ / | \
n_item n_item n_item e_item e_item e_item
So they are 6 types of pages
I then ticked the "Show in menus:" in the promote tab for the starred pages (*) in the above list.
The n_item and e_item will allow the editor (non technical) person to add as many of these pages as they wanted as they will be listed as part of the contents in the "News" and "Events" pages respectively.
Ideally the editor should not create siblings to Home Page,News, About us and events. Is it also possible to limit wagtails functionality of where editors can add pages if they are not super users?
But there doesn't seem to be a clear simple way (maybe a tag) to generate my menu. This is what I have found in my research.
Upvotes: 3
Views: 2418
Reputation: 1244
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.
Upvotes: 2
Reputation: 1451
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".
Upvotes: 1