X-Git-Url: http://git.ithinksw.org/philo.git/blobdiff_plain/2b21f17548ca9c2b1be8c3047ad86370c95fcb9e..92e8e96c8d6814f3bd93ecd82d8da2ccb43e13c4:/contrib/shipherd/templatetags/shipherd.py diff --git a/contrib/shipherd/templatetags/shipherd.py b/contrib/shipherd/templatetags/shipherd.py index af7f05f..b05ff0f 100644 --- a/contrib/shipherd/templatetags/shipherd.py +++ b/contrib/shipherd/templatetags/shipherd.py @@ -1,25 +1,27 @@ -from django import template +from django import template, VERSION as django_version 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 django.utils.safestring import mark_safe from django.utils.translation import ugettext as _ register = template.Library() -class RecurseNavigationMarker(object): - pass - - -class RecurseNavigationNode(template.Node): - def __init__(self, template_nodes, instance_var, key): +class LazyNavigationRecurser(object): + def __init__(self, template_nodes, items, context, request): self.template_nodes = template_nodes - self.instance_var = instance_var - self.key = key + self.items = items + self.context = context + self.request = request - def _render_items(self, items, context, request): + def __call__(self): + items = self.items + context = self.context + request = self.request + if not items: return '' @@ -51,24 +53,29 @@ class RecurseNavigationNode(template.Node): # 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) + # Set these directly in the context for easy access. + context['item'] = item + context['children'] = self.__class__(self.template_nodes, item.get_children(), context, request) + + # Django 1.2.X compatibility - a lazy recurser will not be called if accessed as a template variable. + if django_version < (1,3): + context['children'] = context['children']() + # 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)) + bits.append(node.render(context)) context.pop() - return ''.join(bits) + return mark_safe(''.join(bits)) + + +class RecurseNavigationNode(template.Node): + def __init__(self, template_nodes, instance_var, key_var): + self.template_nodes = template_nodes + self.instance_var = instance_var + self.key_var = key_var def render(self, context): try: @@ -77,34 +84,59 @@ class RecurseNavigationNode(template.Node): return '' instance = self.instance_var.resolve(context) + key = self.key_var.resolve(context) + + # Fall back on old behavior if the key doesn't seem to be a variable. + if not key: + token = self.key_var.token + if token[0] not in ["'", '"'] and '.' not in token: + key = token + else: + return settings.TEMPLATE_STRING_IF_INVALID try: - items = instance.navigation[self.key] + items = instance.navigation[key] except: return settings.TEMPLATE_STRING_IF_INVALID - return self._render_items(items, context, request) + return LazyNavigationRecurser(self.template_nodes, items, context, request)() @register.tag def recursenavigation(parser, token): """ - Based on django-mptt's recursetree templatetag. In addition to {{ item }} and {{ children }}, - sets {{ active }}, {{ active_descendants }}, {{ navloop.counter }}, {{ navloop.counter0 }}, - {{ navloop.revcounter }}, {{ navloop.revcounter0 }}, {{ navloop.first }}, {{ navloop.last }}, - and {{ navloop.parentloop }} in the context. + The recursenavigation templatetag takes two arguments: + - the node for which the navigation should be found + - the navigation's key. + + It will then recursively loop over each item in the navigation and render the template + chunk within the block. recursenavigation sets the following variables in the context: - Note that the tag takes two variables: a Node instance and the key of the navigation to - be recursed. + ============================== ================================================ + Variable Description + ============================== ================================================ + ``navloop.depth`` The current depth of the loop (1 is the top level) + ``navloop.depth0`` The current depth of the loop (0 is the top level) + ``navloop.counter`` The current iteration of the current level(1-indexed) + ``navloop.counter0`` The current iteration of the current level(0-indexed) + ``navloop.first`` True if this is the first time through the current level + ``navloop.last`` True if this is the last time through the current level + ``navloop.parentloop`` This is the loop one level "above" the current one + ============================== ================================================ + ``item`` The current item in the loop (a NavigationItem instance) + ``children`` If accessed, performs the next level of recursion. + ``navloop.active`` True if the item is active for this request + ``navloop.active_descendants`` True if the item has active descendants for this request + ============================== ================================================ - Usage: + Example: