From 2b21f17548ca9c2b1be8c3047ad86370c95fcb9e Mon Sep 17 00:00:00 2001 From: Stephen Burrows Date: Wed, 2 Mar 2011 17:35:20 -0500 Subject: [PATCH] Refactored the RecurseNavigationNode to have less repetition. Switched from {{ children }} to {% recurse %} because it makes more sense to collect recursion only if needed. --- contrib/shipherd/templatetags/shipherd.py | 95 +++++++++++++---------- 1 file changed, 56 insertions(+), 39 deletions(-) diff --git a/contrib/shipherd/templatetags/shipherd.py b/contrib/shipherd/templatetags/shipherd.py index 83e98a2..af7f05f 100644 --- a/contrib/shipherd/templatetags/shipherd.py +++ b/contrib/shipherd/templatetags/shipherd.py @@ -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 %} {{ item.text }} - {% if children %} + {% if item.get_children %} {% endif %} @@ -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) -- 2.20.1