131af82996d9a8e6ed2a6153c916f27791522884
[auf_savoirs_en_partage_django.git] / auf_savoirs_en_partage / savoirs / templatetags / sep.py
1 # -*- encoding: utf-8 -*-
2
3 import re
4 from django import template
5 from django.conf import settings
6 from django.template.defaultfilters import stringfilter
7 from django.utils.encoding import smart_str
8 from datamaster_modeles.models import Region
9 from savoirs.models import Discipline
10
11 register = template.Library()
12
13 @register.inclusion_tag('menu.html', takes_context=True)
14 def sep_menu(context, discipline_active, region_active):
15 regions = Region.objects.filter(actif=True).order_by('nom')
16 disciplines = Discipline.objects.all()
17 return dict(disciplines=disciplines, regions=regions,
18 discipline_active=discipline_active, region_active=region_active,
19 request=context['request'])
20
21 @register.inclusion_tag('sort_link.html', takes_context=True)
22 def sort_link(context, field, label):
23 request = context['request']
24 params = request.GET.copy()
25 current_sort = params.get('tri')
26 if current_sort == field:
27 sort = field + '_desc'
28 indicator = u' (croissant)'
29 else:
30 sort = field
31 if current_sort == field + '_desc':
32 indicator = u' (décroissant)'
33 else:
34 indicator = ''
35
36 params['tri'] = sort
37 url = request.path + '?' + params.urlencode()
38 return dict(label=label, url=url, indicator=indicator)
39
40 class URLNode(template.Node):
41 def __init__(self, view_name, args, kwargs, asvar):
42 self.view_name = view_name
43 self.args = args
44 self.kwargs = kwargs
45 self.asvar = asvar
46
47 def render(self, context):
48 from django.core.urlresolvers import reverse, NoReverseMatch
49 args = [arg.resolve(context) for arg in self.args]
50 kwargs = dict([(smart_str(k,'ascii'), v.resolve(context))
51 for k, v in self.kwargs.items()])
52
53 # C'est ici que nous injectons la discipline et la région courante
54 # dans les arguments.
55 context_discipline = context.get('discipline_active')
56 if context_discipline:
57 kwargs.setdefault('discipline', context_discipline)
58 context_region = context.get('region_active')
59 if context_region:
60 kwargs.setdefault('region', context_region)
61
62 # Try to look up the URL twice: once given the view name, and again
63 # relative to what we guess is the "main" app. If they both fail,
64 # re-raise the NoReverseMatch unless we're using the
65 # {% url ... as var %} construct in which cause return nothing.
66 url = ''
67 try:
68 url = reverse(self.view_name, args=args, kwargs=kwargs, current_app=context.current_app)
69 except NoReverseMatch, e:
70 if settings.SETTINGS_MODULE:
71 project_name = settings.SETTINGS_MODULE.split('.')[0]
72 try:
73 url = reverse(project_name + '.' + self.view_name,
74 args=args, kwargs=kwargs, current_app=context.current_app)
75 except NoReverseMatch:
76 if self.asvar is None:
77 # Re-raise the original exception, not the one with
78 # the path relative to the project. This makes a
79 # better error message.
80 raise e
81 else:
82 if self.asvar is None:
83 raise e
84
85 if self.asvar:
86 context[self.asvar] = url
87 return ''
88 else:
89 return url
90
91 @register.tag
92 def sep_url(parser, token):
93 """
94 Le tag ``url`` de Django, modifié pour SEP.
95
96 Lorsque ce tag est utilisé, la discipline et la région actives sont
97 automatiquement réinjectées dans les URL construites.
98 """
99 bits = token.split_contents()
100 if len(bits) < 2:
101 raise TemplateSyntaxError("'%s' takes at least one argument"
102 " (path to a view)" % bits[0])
103 viewname = bits[1]
104 args = []
105 kwargs = {}
106 asvar = None
107
108 if len(bits) > 2:
109 bits = iter(bits[2:])
110 for bit in bits:
111 if bit == 'as':
112 asvar = bits.next()
113 break
114 else:
115 for arg in bit.split(","):
116 if '=' in arg:
117 k, v = arg.split('=', 1)
118 k = k.strip()
119 kwargs[k] = parser.compile_filter(v)
120 elif arg:
121 args.append(parser.compile_filter(arg))
122 return URLNode(viewname, args, kwargs, asvar)
123
124 DISCIPLINE_REGION_RE = re.compile(r'(/discipline/\d+)?(/region/\d+)?')
125
126 @register.filter
127 @stringfilter
128 def change_region(path, region):
129 """Modifie la région dans le chemin donné."""
130 match = DISCIPLINE_REGION_RE.match(path)
131 discipline_bit = match.group(1) or ''
132 region_bit = '/region/%d' % region if region != 'all' else ''
133 rest = path[match.end():]
134 if not rest.startswith('/recherche/'):
135 rest = '/'
136 return discipline_bit + region_bit + rest
137
138 @register.filter
139 @stringfilter
140 def change_discipline(path, discipline):
141 """Modifie la discipline dans le chemin donné."""
142 match = DISCIPLINE_REGION_RE.match(path)
143 discipline_bit = '/discipline/%d' % discipline if discipline != 'all' else ''
144 region_bit = match.group(2) or ''
145 rest = path[match.end():]
146 if not rest.startswith('/recherche/'):
147 rest = '/'
148 return discipline_bit + region_bit + rest
149
150 @register.filter
151 def apply(value, func):
152 """Applique une fonction arbitraire à la valeur filtrée."""
153 return func(value)
154
155 @register.filter
156 def getitem(container, key):
157 """Applique ``container[key]`` sur la valeur filtrée."""
158 return container.get(key, '')