1 from django import template
2 from django.conf import settings
3 from django.utils.safestring import mark_safe
4 from philo.contrib.shipherd.models import Navigation
5 from philo.models import Node
6 from mptt.templatetags.mptt_tags import RecurseTreeNode, cache_tree_children
7 from django.utils.translation import ugettext as _
10 register = template.Library()
13 class RecurseNavigationNode(RecurseTreeNode):
14 def __init__(self, template_nodes, instance_var, key):
15 self.template_nodes = template_nodes
16 self.instance_var = instance_var
19 def _render_node(self, context, item, request):
22 for child in item.get_children():
23 context['item'] = child
24 bits.append(self._render_node(context, child, request))
25 context['item'] = item
26 context['children'] = mark_safe(u''.join(bits))
27 context['active'] = item.is_active(request)
28 context['active_descendants'] = item.has_active_descendants(request)
29 rendered = self.template_nodes.render(context)
33 def render(self, context):
35 request = context['request']
39 instance = self.instance_var.resolve(context)
42 navigation = instance.navigation[self.key]
44 return settings.TEMPLATE_STRING_IF_INVALID
46 bits = [self._render_node(context, item, request) for item in navigation]
51 def recursenavigation(parser, token):
53 Based on django-mptt's recursetree templatetag. In addition to {{ item }} and {{ children }},
54 sets {{ active }} and {{ active_descendants }} in the context.
56 Note that the tag takes one variable, which is a Node instance.
60 {% recursenavigation node main %}
61 <li{% if active %} class='active'{% endif %}>
63 {% if navigation.get_children %}
69 {% endrecursenavigation %}
72 bits = token.contents.split()
74 raise template.TemplateSyntaxError(_('%s tag requires two arguments: a node and a navigation section name') % bits[0])
76 instance_var = parser.compile_filter(bits[1])
79 template_nodes = parser.parse(('endrecursenavigation',))
80 parser.delete_first_token()
82 return RecurseNavigationNode(template_nodes, instance_var, key)
86 def has_navigation(node): # optional arg for a key?
87 return bool(node.navigation)
91 def navigation_host(node, key):
93 return Navigation.objects.filter(node__in=node.get_ancestors(include_self=True), key=key).order_by('-node__level')[0].node
95 if settings.TEMPLATE_DEBUG: