I would like to redirect the top menu items in a page I'm writing to point at their children if they have any. E.g. this site has a top level About, with several CMS pages underneath. When a user clicks on about, I want to show the first child page under the top-level about menu.
I can do it like the below, but it feels wrong. I know I can do a static redirect, but I don't want to do that, as the first child might change (it's a CMS system after all) and I don't want the people entering data into the CMS to have to manage a redirect. So I prefer the below to a configured redirect.
This is a pretty common requirement, is there a standard way of doing this? I think I might be able to do it with a navigation modifier, so I might try that route next.
<div style="display:none;">{% show_menu 0 1 1 %}</div>
<div id="topmenu">
<ul>
{% for child in children %}
<li>
{% if child.children %}
<a href="{{child.children.0.get_absolute_url}}">
{% else %}
<a href="{{child.get_absolute_url}}">
{% endif %}
{{ child.get_menu_title }}
</a>
</li>
{% endfor %}
</ul>
</div>
About the above, I need to have the show_menu in there otherwise the data isn't there for my custom menu. Is there any way for this not to be needed?
The thing I dislike the most about the above, is that the /about/ page is still active. It's not the worst thing in the world if someone browses there, they'll get an empty page, but I'd rather that not happen. I think if I wrote a navigation extension the same disadvantage would be there. I guess I need a programmatic redirect to redirect to the first child if that page is hit. Thoughts? I can probably do it in template logic, but that seems crazy.
2018: updated version, that works in cms 3.4+ and new middleware style compatible available here. Once you added the /firstchild, you'll need to edit/publish the redirecting page in the cms pages's change list, as, you guess it, will redirect.
solution with middleware and custom redirect field value of "/firstchild", to trigger redirects.
from django.shortcuts import redirect
# redirect to first subpage if the "redirect" field is exactly "_subpage"
class RedirectSubpageMiddleware(object):
def process_view(self, request, view_func, view_args, view_kwargs):
if request.current_page:
page = request.current_page
if "slug" in view_kwargs and page.get_redirect() == "/firstchild":
subpages = request.current_page.children.all()
if subpages.count():
# can redirect! must make uri!
return redirect(subpages[0].get_absolute_url(), permanent=True)
return None