Tri approprié des briques
[auf_savoirs_en_partage_django.git] / auf_savoirs_en_partage / savoirs / templatetags / sep.py
CommitLineData
bae03b7b
EMS
1# -*- encoding: utf-8 -*-
2
c1b134f8 3import re
bae03b7b
EMS
4from django import template
5from django.conf import settings
c1b134f8 6from django.template.defaultfilters import stringfilter
bae03b7b
EMS
7from django.utils.encoding import smart_str
8from datamaster_modeles.models import Region
9from savoirs.models import Discipline
10
c1b134f8
EMS
11register = template.Library()
12
13@register.inclusion_tag('menu.html', takes_context=True)
14def sep_menu(context, discipline_active, region_active):
bae03b7b
EMS
15 regions = Region.objects.filter(actif=True).order_by('nom')
16 disciplines = Discipline.objects.all()
17 return dict(disciplines=disciplines, regions=regions,
c1b134f8
EMS
18 discipline_active=discipline_active, region_active=region_active,
19 request=context['request'])
bae03b7b 20
7020ea3d
EMS
21@register.inclusion_tag('sort_link.html', takes_context=True)
22def 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
bae03b7b
EMS
40class 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.
c1b134f8
EMS
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)
bae03b7b
EMS
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
c1b134f8 91@register.tag
bae03b7b
EMS
92def 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.
bae03b7b
EMS
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)
c1b134f8
EMS
123
124DISCIPLINE_REGION_RE = re.compile(r'(/discipline/\d+)?(/region/\d+)?')
125
126@register.filter
127@stringfilter
128def 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():]
f0692c02
EMS
134 if not rest.startswith('/recherche'):
135 rest = '/'
c1b134f8
EMS
136 return discipline_bit + region_bit + rest
137
138@register.filter
139@stringfilter
140def 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():]
f0692c02
EMS
146 if not rest.startswith('/recherche'):
147 rest = '/'
c1b134f8 148 return discipline_bit + region_bit + rest