53

I would like to render a constructions like:

<a href='/home'>Home</a>
<span class='active'>Community</span>
<a href='/about'>About</a>

Where Community is selected menu item. I have menu with same options for several templates but I would not like to create combinations for each template:

<!-- for Home template-->
        <span class='active'>Home</span>
        <a href='/comminuty'>Community</a>
        <a href='/about'>About</a>
    ...
<!-- for Community template-->
        <a href='/home'>Home</a>
        <span class='active'>Community</span>
        <a href='/about'>About</a>
    ...
<!-- for About template-->
        <a href='/home'>Home</a>
        <a href='/community'>Community</a>
        <span class='active'>About</span>

We have permanent list of menu items, so, it can be more effective way - to create only one generalized structure of menu then render menu with required option for template.

For example it could be a tag that allows to do that.

sergzach
  • 6,578
  • 7
  • 46
  • 84

12 Answers12

104

Figured out another way to do it, elegant enough thanks to this answer : https://stackoverflow.com/a/17614086/34871

Given an url pattern such as:

url(r'^some-url', "myapp.myview", name='my_view_name'),

my_view_name is available to the template through request ( remember you need to use a RequestContext - which is implicit when using render_to_response )

Then menu items may look like :

<li class="{% if request.resolver_match.url_name == "my_view_name" %}active{% endif %}"><a href="{% url "my_view_name" %}">Shortcut1</a></li>
<li class="{% if request.resolver_match.url_name == "my_view_name2" %}active{% endif %}"><a href="{% url "my_view_name2" %}">Shortcut2</a></li>

etc.

This way, the url can change and it still works if url parameters vary, and you don't need to keep a list of menu items elsewhere.

Community
  • 1
  • 1
vincent
  • 6,368
  • 3
  • 25
  • 23
  • 1
    just wanted to say that this is perfect because it allows you to use this in a single 'global' template instead of implementing the same thing several times in individual template files. thanks – Jack Sep 02 '15 at 22:20
  • 1
    `request.resolver_match.url_name` does not return a namespaced name. – Flimm May 13 '16 at 12:09
  • 6
    use `request.resolver_match.view_name` for namespaced name – zhenming Jul 13 '16 at 04:55
  • 6
    This is an excellent solution. Much easier and more elegant than the others. – larapsodia Aug 29 '16 at 01:43
  • This won't work if you have submenus and want the parent '
  • ' item to have the 'active' class. (It would work if you expand the if statement to accept all sub-views but you don't want to go down that route.)
  • – kristian Sep 17 '16 at 20:13
  • 2
    This answer is the cleanest to implement. I read many posts on the forum and they are pulling off complicated solutions, but for most of us that are not going to develop a very big app this works just like a charm. I'd like to add one thing: most likely, one will need to have 2 class names in the html, one for styling the menu items if they are not selected, and one for the case they are selected/active. I give an example in the next comment. – Ibo Sep 29 '17 at 17:44
  • 1
    Example applying 2 classes to meny items: `{% else %}` template tag would suffice: `
  • ` – Ibo Sep 29 '17 at 17:47
  • This is the best solution – Sanidhya Singh Apr 21 '20 at 10:51