3

A standard Wagtail breadcrumb system like this works perfectly if all of your pages are in a tree (parents/children):

{% block main %}
    {% if self.get_ancestors|length > 1 %}
        <ul class="breadcrumb">
            {% for page in self.get_ancestors %}
                {% if page.is_root == False and page.url != '/' %}
                    <li><a href="{% pageurl page %}">{{ page.title }}</a></li>
                {% endif %}
            {% endfor %}
            <li class="active">{{ self.title }}</li>
        </ul>
    {% endif %}
{% endblock main %}

But it falls down if some of your sub-pages are not actual children, but instead use RoutablePageMixin. Because the routable pages are really different instances of the parent, the breadcrumb trail stops short of making it down to the routable page.

I thought I could add some extra info to the context to detect the situation and special-case it, but all of the WT URL methods return the URL of the "parent" page (i.e. the actual instance), and besides there is no programmatic "title" that could be used in the breadcrumb.

What's the best way to have a breadcrumb system that works equally well for child pages and routable pages?

shacker
  • 14,712
  • 8
  • 89
  • 89

2 Answers2

3

Answering my own question (Thanks Robert for the hint). In the route definition in the model, add something like:

ctx['routed_title'] = 'Staff'

Then modify the breadcrumb example above like this (check for existence of the new element on context and append to breadcrumbs):

{% block main %}
    {% if self.get_ancestors|length > 1 %}
        <ul class="breadcrumb">
            {% for page in self.get_ancestors %}
                {% if page.is_root == False and page.url != '/' %}
                    <li><a href="{% pageurl page %}">{{ page.title }}</a></li>
                {% endif %}
            {% endfor %}
            {# If this is a routable, add non-parent/child link from context #}
            {% if routed_title %}
                <li><a href="{% pageurl page %}">{{ page.title }}</a></li>
                <li class="active">{{ routed_title }}</li>
            {% else %}
                <li class="active">{{ self.title }}</li>
            {% endif %}
        </ul>
    {% endif %}
{% endblock main %}
shacker
  • 14,712
  • 8
  • 89
  • 89
1

Maybe this can be of any help.

@route(_(r'^detail/(?P<activity_slug>[-\w]+)/$'))
def show_activity(self, request, activity_slug):
    activity_model_class = self.activity_model_class
    if not activity_model_class:
        raise Http404('No activity model.')
    else:
        queryset = self.get_activity(activity_slug)
        try:
            activity = queryset.get()
        except activity_model_class.DoesNotExist:
            raise Http404('activity not found')
        else:
            self.current_url = self.get_url(
                'show_activity',
                kwargs = {'activity_slug': activity_slug}
            )

Now the routable page has a current_url

def get_context(self, request, *args, **kwargs):
        context = super().get_context(request)
        context['current_url']= self.current_url
    return context

And now it’s in the context.

Robert
  • 261
  • 2
  • 11
  • Robert thanks - but how do you access a page title for use in the breadcrumbs with this technique? – shacker Jan 25 '17 at 19:49
  • Do you mean the title of the last page in the crumbs path? – Robert Jan 26 '17 at 09:30
  • Yes - the title of the routable page that this technique is meant to bring in. I guess you could code it into context - the element referred to as self.title in my OP. – shacker Jan 26 '17 at 18:13
  • Figured it out - see answer below. Thanks for pointing me in the right direction. – shacker Jan 26 '17 at 18:34