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
9 register = template.Library()
12 class RecurseNavigationNode(RecurseTreeNode):
13 def __init__(self, template_nodes, instance_var):
14 self.template_nodes = template_nodes
15 self.instance_var = instance_var
17 def _render_node(self, context, node, request):
20 for child in node.get_children():
21 context['navigation'] = child
22 bits.append(self._render_node(context, child, request))
23 context['navigation'] = node
24 context['children'] = mark_safe(u''.join(bits))
25 context['active'] = node.is_active(request)
26 rendered = self.template_nodes.render(context)
30 def render(self, context):
32 request = context['request']
36 instance = self.instance_var.resolve(context)
38 if isinstance(instance, Node):
39 qs = Navigation.objects.closest_navigation(instance)
40 elif hasattr(instance, '__iter__'):
41 # Is this the right way to check?
44 return settings.TEMPLATE_STRING_IF_INVALID
46 roots = cache_tree_children(qs)
47 bits = [self._render_node(context, node, request) for node in roots]
52 def recursenavigation(parser, token):
54 Based on django-mptt's recursetree templatetag. In addition to {{ navigation }} and {{ children }},
55 sets {{ active }} in the context.
57 Note that the tag takes one variable, which is a Node instance.
61 {% recursenavigation node %}
62 <li{% if active %} class='active'{% endif %}>
64 {% if not navigation.is_leaf_node %}
70 {% endrecursenavigation %}
73 bits = token.contents.split()
75 raise template.TemplateSyntaxError(_('%s tag requires an instance') % bits[0])
77 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)
86 def has_navigation(node):
87 return bool(Navigation.objects.closest_navigation(node).count())
91 def targeting_navigation(node):
92 return Navigation.objects.closest_navigation(node).filter(target_node=node).order_by('level', 'lft')