Refactored the RecurseNavigationNode to have less repetition. Switched from {{ childr...
authorStephen Burrows <stephen.r.burrows@gmail.com>
Wed, 2 Mar 2011 22:35:20 +0000 (17:35 -0500)
committerStephen Burrows <stephen.r.burrows@gmail.com>
Wed, 2 Mar 2011 22:35:20 +0000 (17:35 -0500)
contrib/shipherd/templatetags/shipherd.py

index 83e98a2..af7f05f 100644 (file)
@@ -3,45 +3,72 @@ from django.conf import settings
 from django.utils.safestring import mark_safe
 from philo.contrib.shipherd.models import Navigation
 from philo.models import Node
-from mptt.templatetags.mptt_tags import RecurseTreeNode, cache_tree_children
 from django.utils.translation import ugettext as _
 
 
 register = template.Library()
 
 
-class RecurseNavigationNode(RecurseTreeNode):
+class RecurseNavigationMarker(object):
+       pass
+
+
+class RecurseNavigationNode(template.Node):
        def __init__(self, template_nodes, instance_var, key):
                self.template_nodes = template_nodes
                self.instance_var = instance_var
                self.key = key
        
-       def _render_node(self, context, item, request):
-               bits = []
+       def _render_items(self, items, context, request):
+               if not items:
+                       return ''
+               
+               if 'navloop' in context:
+                       parentloop = context['navloop']
+               else:
+                       parentloop = {}
                context.push()
                
-               # loosely based on django.template.defaulttags.ForNode.render
-               children = item.get_children()
-               parentloop = context['navloop']
-               loop_dict = context['navloop'] = {'parentloop':parentloop}
-               len_items = len(children)
-               for i, child in enumerate(children):
-                       context['item'] = child
+               depth = items[0].get_level()
+               len_items = len(items)
+               
+               loop_dict = context['navloop'] = {
+                       'parentloop': parentloop,
+                       'depth': depth + 1,
+                       'depth0': depth
+               }
+               
+               bits = []
+               
+               for i, item in enumerate(items):
+                       # First set context variables.
                        loop_dict['counter0'] = i
                        loop_dict['counter'] = i + 1
                        loop_dict['revcounter'] = len_items - i
                        loop_dict['revcounter0'] = len_items - i - 1
                        loop_dict['first'] = (i == 0)
                        loop_dict['last'] = (i == len_items - 1)
-                       bits.append(self._render_node(context, child, request))
-               context['navloop'] = context['navloop']['parentloop']
-               context['item'] = item
-               context['children'] = mark_safe(u''.join(bits))
-               context['active'] = item.is_active(request)
-               context['active_descendants'] = item.has_active_descendants(request)
-               rendered = self.template_nodes.render(context)
+                       
+                       # Set on loop_dict and context for backwards-compatibility.
+                       # Eventually only allow access through the loop_dict.
+                       loop_dict['item'] = context['item'] = item
+                       loop_dict['active'] = context['active'] = item.is_active(request)
+                       loop_dict['active_descendants'] = context['active_descendants'] = item.has_active_descendants(request)
+                       
+                       # Then render the nodelist bit by bit.
+                       for node in self.template_nodes:
+                               if isinstance(node, RecurseNavigationMarker):
+                                       # Then recurse!
+                                       children = items.get_children()
+                                       bits.append(self._render_items(children, context, request))
+                               elif isinstance(node, template.VariableNode) and node.filter_expression.var.lookups == (u'children',):
+                                       # Then recurse! This is here for backwards-compatibility only.
+                                       children = items.get_children()
+                                       bits.append(self._render_items(children, context, request))
+                               else:
+                                       bits.append(node.render(context))
                context.pop()
-               return rendered
+               return ''.join(bits)
        
        def render(self, context):
                try:
@@ -56,22 +83,7 @@ class RecurseNavigationNode(RecurseTreeNode):
                except:
                        return settings.TEMPLATE_STRING_IF_INVALID
                
-               bits = []
-               
-               # loosely based on django.template.defaulttags.ForNode.render
-               # This is a repetition of the stuff that happens above. We should eliminate that somehow.
-               loop_dict = context['navloop'] = {'parentloop':{}}
-               len_items = len(items)
-               for i, item in enumerate(items):
-                       loop_dict['counter0'] = i
-                       loop_dict['counter'] = i + 1
-                       loop_dict['revcounter'] = len_items - i
-                       loop_dict['revcounter0'] = len_items - i - 1
-                       loop_dict['first'] = (i == 0)
-                       loop_dict['last'] = (i == len_items - 1)
-                       bits.append(self._render_node(context, item, request))
-               
-               return ''.join(bits)
+               return self._render_items(items, context, request)
 
 
 @register.tag
@@ -90,9 +102,9 @@ def recursenavigation(parser, token):
                        {% recursenavigation node main %}
                                <li{% if active %} class='active'{% endif %}>
                                        {{ item.text }}
-                                       {% if children %}
+                                       {% if item.get_children %}
                                                <ul>
-                                                       {{ children }}
+                                                       {% recurse %}
                                                </ul>
                                        {% endif %}
                                </li>
@@ -106,8 +118,13 @@ def recursenavigation(parser, token):
        instance_var = parser.compile_filter(bits[1])
        key = bits[2]
        
-       template_nodes = parser.parse(('endrecursenavigation',))
-       parser.delete_first_token()
+       template_nodes = parser.parse(('recurse', 'endrecursenavigation',))
+       
+       token = parser.next_token()
+       if token.contents == 'recurse':
+               template_nodes.append(RecurseNavigationMarker())
+               template_nodes.extend(parser.parse(('endrecursenavigation')))
+               parser.delete_first_token()
        
        return RecurseNavigationNode(template_nodes, instance_var, key)