randombits
randombits

Reputation: 48450

Navigation menu using Django templates

Trying to work with a trivial navigation menu using django templates, I'm having trouble setting the current class on a particular menu item. Here's my base template:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
 <title>{% block title %}{% endblock %}</title> 
 <meta http-equiv="content-type" content="text/html;charset=utf-8" />
 <link rel="stylesheet" type="text/css" href="/media/css/base.css" />
 <link rel="stylesheet" type="text/css" href="/media/css/login.css" />
 <link rel="stylesheet" href="/site_media/css/style.css" type="text/css" />
 <!--[if lte IE 7]><link rel="stylesheet" type="text/css" href="/media/css/ie.css" /><![endif]-->
</head>
 <body class="{% block bodyclass %}{% endblock %}">
 {% block content %}{% endblock %} 
 {% block footer %}{% endblock %}
</body> 
</html>

Then I have a nav.html:

 <ul id="top">
   <li><a class="{% block home %}{% endblock %}" href="/">Home</a></li>
   <li><a class="{% block myaccount %}{% endblock %}" href="/profile/">My Account</a></li>
   {% if perms.staffing.add_staffrequest %}
    <li><a class="{% block createsr %}{% endblock %}" 
     href="/create/staffrequest/">Staff Request</a></li>
   {% endif %}
  </ul>

And now in my home.html, I can't seem to get the class current to display:

{% extends "base.html" %}
{% block title %}Home Portal{% endblock %}
{% block content %}

<div id="content">
 {% include "nav.html" %}
    {% block home %}current{% endblock %} 
 <div id="intro">
  <p>Hello, {{ user.first_name }}.</p>
  <p>Please create a Staff Request here by filling out the form
  below.</p>
 </div> <!-- end intro -->
 <div id="logout">
  <a href="/accounts/logout" alt="Sign Off" title="Sign Off">Sign Off</a>
 </div>
</div> <!-- end content -->

{% endblock %}

The class 'current' isn't showing up in navigation for the appropriate element, letting me set visual context for a user depending what page they're on.

Upvotes: 7

Views: 19033

Answers (3)

sergzach
sergzach

Reputation: 6754

You can solve the duplication problem using DRY menu custom template tag. It solves the problem of active/inactive menu class too. See the description below, please. The source code: http://djangosnippets.org/snippets/2722/

Description of DRY menu template tag.

This is the description of a custom template tag to create DRY menu. It solves the problem of markup duplication in templates of your site. The menu always has one active option and one or several inactive options.

HOW TO USE

Define a structure of your menu in a parent template:

{% defmenu "menu1" %}

{% active %}<span class='active'>{{text}}</span>{% endactive %}
{% inactive %}<a href='{{url}}'>{{text}}</a>{% endinactive %}

{% opt "opt1" "/opt1/" %}Go to opt1{% endopt %}
{% opt "opt2" "/opt2/" %}Go to opt2{% endopt %}
{% opt "opt3" "/opt3/" %}Go to opt3{% endopt %}

{% enddefmenu %}

The menu has it's name (first parameter of the tag 'defmenu'.

First parameter of a tag 'opt' is menu option's name. 'text' inside of 'active'/'inactive' will be substituted by inner text of a tag 'opt' (Go to opt...), 'url' indide of 'active'/'inactive' will be substituted by second parameter of a tag 'opt'

To generate menu with one selected option in child template do:

{% menu "menu1" "opt1" %}

Here: "menu1" is a name of menu that was defined by 'defmenu' tag, "opt1" is selected option.

Result of the applying 'menu' is the next:

<span class='active'> Go to opt1</span> <a href='"/opt2/"'>Go to opt2</a> <a href='"/opt3/"'>Go to opt3</a>

Upvotes: 0

T. Stone
T. Stone

Reputation: 19495

The other way people handle this is to just use the body.class in the CSS file...

nav.html

 <ul id="top">
   <li><a class="home" href="/">Home</a></li>
   <li><a class="myaccount" href="/profile/">My Account</a></li>
   {% if perms.staffing.add_staffrequest %}
    <li><a class="createsr" 
     href="/create/staffrequest/">Staff Request</a></li>
   {% endif %}
  </ul>

home.html

{% block bodyclass %}home{% endblock %}

your css file

body.home li.home { font-weight: bold; color: blue; }
body.myaccount li.myaccount { font-weight: bold; color: blue; }
body.createsr li.createsr { font-weight: bold; color: blue; }

It breaks DRY but sometimes it's simpler than messing with some crazy blocked templates.

Upvotes: 2

ikkebr
ikkebr

Reputation: 801

I don't think you can replace a block from an included template. My suggestion is that you need to rethink the logic of your templates. IMHO it should be something like this:

base.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
 <title>{% block title %}{% endblock %}</title> 
 <meta http-equiv="content-type" content="text/html;charset=utf-8" />
  <link rel="stylesheet" type="text/css" href="/media/css/base.css" />
  <link rel="stylesheet" type="text/css" href="/media/css/login.css" />
  <link rel="stylesheet" href="/site_media/css/style.css" type="text/css" />
  <!--[if lte IE 7]><link rel="stylesheet" type="text/css" href="/media/css/ie.css" /><![endif]-->
 </head>
  <body class="{% block bodyclass %}{% endblock %}">
  {% block content %}

     <div id="content">

         {% block navigation %}
             <ul id="top">
                <li><a class="{% block home %}{% endblock %}" href="/">Home</a></li>
                <li><a class="{% block myaccount %}{% endblock %}" href="/profile/">My Account</a></li>
                {% if perms.staffing.add_staffrequest %}
                 <li><a class="{% block createsr %}{% endblock %}" 
                  href="/create/staffrequest/">Staff Request</a></li>
                {% endif %}
             </ul>
         {% endblock %}

         {% block real_content %}
         <div id="intro">
             <p>Hello, {{ user.first_name }}.</p>
             <p>Please create a Staff Request here by filling out the form below.</p>
          </div> <!-- end intro -->

          <div id="logout">
           <a href="/accounts/logout" alt="Sign Off" title="Sign Off">Sign Off</a>
          </div>
          {% endblock %}

     </div> <!-- end content -->


  {% endblock %} 
  {% block footer %}{% endblock %}
 </body> 
 </html>

and your home.html should look like

{% extends "base.html" %}
{% block title %}Home Portal{% endblock %}

{% block home %}current{% endblock %}


{% block real_content %}

<div id="content">

 <div id="intro">
  <p>Hello, {{ user.first_name }}.</p>
  <p>Please create a Staff Request here by filling out the form
  below.</p>
 </div> <!-- end intro -->
 <div id="logout">
  <a href="/accounts/logout" alt="Sign Off" title="Sign Off">Sign Off</a>
 </div>
</div> <!-- end content -->

{% endblock %}

Upvotes: 8

Related Questions