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:
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
{% recursenavigation node main %}
<li{% if active %} class='active'{% endif %}>
{{ item.text }}
- {% if children %}
+ {% if item.get_children %}
<ul>
- {{ children }}
+ {% recurse %}
</ul>
{% endif %}
</li>
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)