fa4ec3eed66c105ca4291144329ba9849de4208c
[philo.git] / contrib / shipherd / templatetags / shipherd.py
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
7 from django.utils.translation import ugettext as _
8
9
10 register = template.Library()
11
12
13 class RecurseNavigationNode(RecurseTreeNode):
14         def __init__(self, template_nodes, instance_var, key):
15                 self.template_nodes = template_nodes
16                 self.instance_var = instance_var
17                 self.key = key
18         
19         def _render_node(self, context, item, request):
20                 bits = []
21                 context.push()
22                 for child in item.get_children():
23                         context['item'] = child
24                         bits.append(self._render_node(context, child, request))
25                 context['item'] = item
26                 context['children'] = mark_safe(u''.join(bits))
27                 context['active'] = item.is_active(request)
28                 context['active_descendants'] = item.has_active_descendants(request)
29                 rendered = self.template_nodes.render(context)
30                 context.pop()
31                 return rendered
32         
33         def render(self, context):
34                 try:
35                         request = context['request']
36                 except KeyError:
37                         return ''
38                 
39                 instance = self.instance_var.resolve(context)
40                 
41                 try:
42                         navigation = instance.navigation[self.key]
43                 except:
44                         return settings.TEMPLATE_STRING_IF_INVALID
45                 
46                 bits = [self._render_node(context, item, request) for item in navigation]
47                 return ''.join(bits)
48
49
50 @register.tag
51 def recursenavigation(parser, token):
52         """
53         Based on django-mptt's recursetree templatetag. In addition to {{ item }} and {{ children }},
54         sets {{ active }} and {{ active_descendants }} in the context.
55         
56         Note that the tag takes one variable, which is a Node instance.
57         
58         Usage:
59                 <ul>
60                         {% recursenavigation node main %}
61                                 <li{% if active %} class='active'{% endif %}>
62                                         {{ navigation.text }}
63                                         {% if navigation.get_children %}
64                                                 <ul>
65                                                         {{ children }}
66                                                 </ul>
67                                         {% endif %}
68                                 </li>
69                         {% endrecursenavigation %}
70                 </ul>
71         """
72         bits = token.contents.split()
73         if len(bits) != 3:
74                 raise template.TemplateSyntaxError(_('%s tag requires two arguments: a node and a navigation section name') % bits[0])
75         
76         instance_var = parser.compile_filter(bits[1])
77         key = bits[2]
78         
79         template_nodes = parser.parse(('endrecursenavigation',))
80         parser.delete_first_token()
81         
82         return RecurseNavigationNode(template_nodes, instance_var, key)
83
84
85 @register.filter
86 def has_navigation(node, key=None):
87         try:
88                 nav = node.navigation
89                 if key is not None:
90                         if key in nav and bool(node.navigation[key]):
91                                 return True
92                         elif key not in node.navigation:
93                                 return False
94                 return bool(node.navigation)
95         except:
96                 return False
97
98
99 @register.filter
100 def navigation_host(node, key):
101         try:
102                 return Navigation.objects.filter(node__in=node.get_ancestors(include_self=True), key=key).order_by('-node__level')[0].node
103         except:
104                 if settings.TEMPLATE_DEBUG:
105                         raise
106                 return node