I'm sure I've seen this question on Stack Overflow before, but I couldn't find it by my life, so here goes nothing.
I have a normal Django menu which uses the {% url %}
tag and static names for the menu items. Now I want to have a different style for the menu item which has been selected. But the menu is being rendered in the base template, so how do I figure out which menu item it is?
How about a custom tag which you use to generate your nav item?
The following takes the name of the url for which a nav item should be generated and the text it should display. It generates a li tag with a class of "selected" if the named url's path is the same as the current url (requires
'django.core.context_processors.request'
in yourTEMPLATE_CONTEXT_PROCESSORS
). Within the li, it generates an a tag with the path of the url specified by theurl_name
. It has the contents specified bycontents
.Obviously, this could be tweaked to generate different markup for the nav item, as required.
The rest can be done using CSS.
Advantages:
Easy to use
Little code required
DRY
Could be made to be more flexible
Disadvantages:
Requires
'django.core.context_processors.request'
Requires urls to be named e.g.
urlpatterns = patterns('django.views.generic.simple', ... (r'^$', 'direct_to_template', {'template': 'index.html'}, 'index'), ... )
. This could potentially be done differently (e.g. pass in url).Doesn't cope with pages not exactly equal to the specified and therefore will not apply the selected class to the li when on a page lower in the url heirarchy. For example, if I'm on /products/, it will highlight the nav item directing to /products/. If I'm on /products/myProduct/, it will not highlight the /products/ link. This could be coded around, but it would force people to use sensible urls. For example, change the
additionalAttrs
assignment toadditionalAttrs = ' class=selected' if (context['request'].path.startswith(path) and path != '/') or (context['request'].path == path) else ''
.Code:
You could surely do this with some ugly template code, but a better more globally known way is to use a CSS selector. This lets CSS do all of the work automatically for you.
Here's how it works:
You simply put an id in your body depending on which page you are on. Then in css you do something like this:
You put the nav-aboutme, and nav-contact ids on each of your menu items.
The style will automatically be selected by CSS depending on which body id they are inside of.
I normally do it the way Brian suggested, but to accommodate for a template which a designer gave me which used the more common
class="selected"
method, I wrote a {% nav %} template tag.Your HTML navigation template will look something like:
To set the navigation in a child template, do:
You can pass request.path to your template
then use an ugly if template tag to add a CSS class to your menu item