- Author:
- SmileyChris
- Posted:
- September 15, 2009
- Language:
- Python
- Version:
- 1.1
- Score:
- 0 (after 0 ratings)
Handles navigation item selection.
See the nav
docstring for details.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | from django import template
from django.utils.encoding import smart_str
register = template.Library()
class NavNode(template.Node):
def __init__(self, item=None, var_name=None):
self.item = item
self.var_name = var_name or 'nav'
def render(self, context):
# If the nav variable is already set (to a non-empty value), don't do
# anything.
if context.get(self.var_name):
return ''
# If self.item was blank, just set the nav variable to the context
# (useful to put the nav in a higher context stack)
if not self.item:
context[self.var_name] = {}
return ''
item = self.item.resolve(context)
item = item and smart_str(item)
if not item:
return ''
value = True
for part in reversed(item.split('.')):
new_item = {}
new_item[part] = value
value = new_item
# The nav variable could have been set (as an empty dict) on a higher
# context stack. Try getting it from the context, otherwise set it to
# the current context stack.
nav = context.get(self.var_name)
if not isinstance(nav, dict):
nav = {}
context[self.var_name] = nav
nav.update(new_item)
return ''
def __repr__(self):
return "<Nav node>"
@register.tag
def nav(parser, token):
"""
Handles navigation item selection.
Example usage::
{# Set up the variable for use across context-stacking tags #}
{% nav %} or {% nav for mynav %}
{# Set the context so {{ nav.home }} (or {{ mynav.home }}) is True #}
{% nav "home" %} or {% nav "home" for mynav %}
The most basic (and common) use of the tag is to call ``{% nav [item] %}``,
where ``[item]`` is the item you want to check is selected.
By default, this tag creates a ``nav`` context variable. To use an
alternate context variable name, call ``{% nav [item] for [var_name] %}``.
To use this tag across ``{% block %}`` tags (or other context-stacking
template tags such as ``{% for %}``), call the tag without specifying an
item.
Your HTML navigation template should look something like::
{% block nav %}
<ul class="nav">
<li{% if nav.home %} class="selected"{% endif %}><a href="/">Home</a></li>
<li{% if nav.about %} class="selected"{% endif %}><a href="/about/">About</a></li>
</ul>
{% endblock %}
To override this in a child template, you'd do::
{% include "base.html" %}
{% load nav %}
{% block nav %}
{% nav "about" %}
{{ block.super }}
{% endblock %}
This works for multiple levels of template inheritance, due to the fact
that the tag only does anything if the ``nav`` context variable does not
exist. So only the first ``{% nav %}`` call found will ever be processed.
To create a sub-menu you can check against, simply dot-separate the item::
{% nav "about_menu.info" %}
This will be pass for both ``{% if nav.about_menu %}`` and
``{% if nav.about_menu.info %}``.
"""
bits = token.split_contents()
if len(bits) > 2:
var_name = bits.pop()
for_bit = bits.pop()
if for_bit != 'for' or len(bits) > 2:
raise template.TemplateSyntaxError('Unexpected format for %s tag' %
bits[0])
else:
var_name = 'nav'
if len(bits) > 1:
item = parser.compile_filter(bits[1])
else:
item = None
return NavNode(item, var_name)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 9 months ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 9 months, 1 week ago
- Serializer factory with Django Rest Framework by julio 1 year, 4 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 4 months ago
- Help text hyperlinks by sa2812 1 year, 5 months ago
Comments
Thanks for that SmileyChris!
Whilst I can understand how to use this code, based on your documentation, I am not sure where I should paste it?
Can it just go anywhere, or does it need to go somewhere specific like [appname]/models.py?
#
for extra sugar replace lines 27-31:
So you can just say class="{{ nav.somesection.selected }}". You should probably change the docstring too:
#
Please login first before commenting.