views:

181

answers:

5

Hello everyone

I have templates of this style

project
- main_templates (including nav bar)
-- app1
--- app1_base_template
--- app1_templates
-- app2
--- app2_base_template
--- app2_templates

So when rendering, app2_templates extends app2_base_template which extends main_template.

What I need to do, is have the corresponding nav item be bold when app2's template is being rendered (to show the user where he is).

The easiest would if I could pass a variable in the {% block xxx %} part. Is this possible ?

What other generic ways are there ?

Thanks

+1  A: 

Variables from the parent template are automatically included in the child's scope. Your title says you want to pass a variable TO the parent, which doesn't make sense, as you can't define variables in templates. If you need it a variable in the both the parent and the child, just declare it in the view.

Chase Seibert
+1  A: 

There's no direct way to pass a variable up the template inheritance tree the way you describe. The way that people implement navigation bars that highlight the current page is often tweaked to the nature of the site itself. That said, I've seen two common approaches:

The low-tech approach

Pass a variable in the template context that indicates which tab is active:

# in views.py
def my_view(request):
    return render_to_response('app2_template.html', {"active_tab": "bar"},

<!-- Parent template -->
<div id="navigation">
    <a href="/foo" {% ifequal active_tab "foo" %}class="active"{% endifequal %}>Foo</a>
    <a href="/bar" {% ifequal active_tab "bar" %}class="active"{% endifequal %}>Bar</a>
</div>

The higher-tech approach

Implement a custom template tag to render your navigation bar. Have the tag take a variable that indicates which section is active:

<!-- Parent template -->

<div id="navigation">{% block mainnav %}{% endblock %}</div>

<!-- any child template -->
{% load my_custom_nav_tag %}
{% block mainnav %}{% my_custom_nav_tag "tab_that_is_active" %}{% endblock %}

You can pretty much go crazy from there. You may find that someone has already implemented something that will work for you on djangosnippets.org.

Jarret Hardie
A: 

Sadly I can't find a clean way.

Ended up putting a tag in each app's base.html:

<span class="main_nav_bar_hint" id="2"></span>

(Actually I use two. One set by app's base for the main nav. One set by app pages for app's nav bar)

And a bit of JQuery magic in the project base.html

$(document).ready(function() { $("#nav_menu_" + $(".main_nav_bar_hint").attr("id")).removeClass("normal").addClass("selected"); })

Its a bit of a hack, but this way its easy to understand and I only need to make logical changes once more apps are added.

Murkin
+1  A: 

Inability to pass args on template inclusion is one of many failings of the Django template system.

I had to deal with an almost identical problem: Deeply nested templates needed to cause parent templates to format/highlight differently.

Possible solutions:

  1. Use a "super context" routine that sets a number of values based on where in the hierarchy you are. I.e. super_context = MySuperContext(request, other, values, etc.), where super_context is a dict you pass to the view (or to RequestContext). This is the most Django-thnonic(?) approach, but it means that presentation logic has been pushed back into the views, which feels wrong to me.

  2. Use the expr template tag to set values in the lower level templates. Note: this only works when you {% include %} a template because it must be evaluated before the inclusion occurs. You can't do that with an {% extends %} because that must be the first thing in the child template.

  3. Switch to Jinja2 templating, at least for the views where you need to do this.

Once you have these values set you can do things like this:

<div class="foo{% if foo_active%}_active{%endif%}"> stuff </div>

This makes the div class "foo" when it's not active and "foo_active" when it is. Style to taste, but don't add too much cinnamon. :-)

Peter Rowell
A: 

Have you tried the {% with %} template tag?

{% block content %}
  {% with 'myvar' as expectedVarName %}
  {{block.super}}
  {% endwith %}
{% endblock content %}
czarchaic