1 # -*- encoding: utf-8 -*-
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 django
.utils
.safestring
import mark_safe
9 from datamaster_modeles
.models
import Region
10 from savoirs
.models
import Discipline
12 register
= template
.Library()
14 @register.inclusion_tag('menu.html', takes_context
=True)
15 def sep_menu(context
, discipline_active
, region_active
):
16 regions
= Region
.objects
.filter(actif
=True).order_by('nom')
17 disciplines
= Discipline
.objects
.all()
18 return dict(disciplines
=disciplines
, regions
=regions
,
19 discipline_active
=discipline_active
, region_active
=region_active
,
20 request
=context
['request'])
22 @register.inclusion_tag('menu_brique.html', takes_context
=True)
23 def sep_menu_brique(context
, discipline_active
, region_active
):
24 regions
= Region
.objects
.filter(actif
=True).order_by('nom')
25 disciplines
= Discipline
.objects
.all()
26 return dict(disciplines
=disciplines
, regions
=regions
,
27 discipline_active
=discipline_active
, region_active
=region_active
,
28 request
=context
['request'])
30 @register.inclusion_tag('sort_link.html', takes_context
=True)
31 def sort_link(context
, field
, label
):
32 request
= context
['request']
33 params
= request
.GET
.copy()
34 current_sort
= params
.get('tri')
35 if current_sort
== field
:
36 sort
= field
+ '_desc'
37 indicator
= u
' (croissant)'
40 if current_sort
== field
+ '_desc':
41 indicator
= u
' (décroissant)'
46 url
= request
.path
+ '?' + params
.urlencode()
47 return dict(label
=label
, url
=url
, indicator
=indicator
)
49 class URLNode(template
.Node
):
50 def __init__(self
, view_name
, args
, kwargs
, asvar
):
51 self
.view_name
= view_name
56 def render(self
, context
):
57 from django
.core
.urlresolvers
import reverse
, NoReverseMatch
58 args
= [arg
.resolve(context
) for arg
in self
.args
]
59 kwargs
= dict([(smart_str(k
,'ascii'), v
.resolve(context
))
60 for k
, v
in self
.kwargs
.items()])
62 # C'est ici que nous injectons la discipline et la région courante
64 context_discipline
= context
.get('discipline_active')
65 if context_discipline
:
66 kwargs
.setdefault('discipline', context_discipline
)
67 context_region
= context
.get('region_active')
69 kwargs
.setdefault('region', context_region
)
71 # Try to look up the URL twice: once given the view name, and again
72 # relative to what we guess is the "main" app. If they both fail,
73 # re-raise the NoReverseMatch unless we're using the
74 # {% url ... as var %} construct in which cause return nothing.
77 url
= reverse(self
.view_name
, args
=args
, kwargs
=kwargs
, current_app
=context
.current_app
)
78 except NoReverseMatch
, e
:
79 if settings
.SETTINGS_MODULE
:
80 project_name
= settings
.SETTINGS_MODULE
.split('.')[0]
82 url
= reverse(project_name
+ '.' + self
.view_name
,
83 args
=args
, kwargs
=kwargs
, current_app
=context
.current_app
)
84 except NoReverseMatch
:
85 if self
.asvar
is None:
86 # Re-raise the original exception, not the one with
87 # the path relative to the project. This makes a
88 # better error message.
91 if self
.asvar
is None:
95 context
[self
.asvar
] = url
101 def sep_url(parser
, token
):
103 Le tag ``url`` de Django, modifié pour SEP.
105 Lorsque ce tag est utilisé, la discipline et la région actives sont
106 automatiquement réinjectées dans les URL construites.
108 bits
= token
.split_contents()
110 raise TemplateSyntaxError("'%s' takes at least one argument"
111 " (path to a view)" % bits
[0])
118 bits
= iter(bits
[2:])
124 for arg
in bit
.split(","):
126 k
, v
= arg
.split('=', 1)
128 kwargs
[k
] = parser
.compile_filter(v
)
130 args
.append(parser
.compile_filter(arg
))
131 return URLNode(viewname
, args
, kwargs
, asvar
)
133 DISCIPLINE_REGION_RE
= re
.compile(r
'(/discipline/\d+)?(/region/\d+)?')
137 def change_region(path
, region
):
138 """Modifie la région dans le chemin donné."""
139 match
= DISCIPLINE_REGION_RE
.match(path
)
140 discipline_bit
= match
.group(1) or ''
141 region_bit
= '/region/%d' % region
if region
!= 'all' else ''
142 rest
= path
[match
.end():]
143 if not rest
.startswith('/recherche/'):
145 return discipline_bit
+ region_bit
+ rest
149 def change_discipline(path
, discipline
):
150 """Modifie la discipline dans le chemin donné."""
151 match
= DISCIPLINE_REGION_RE
.match(path
)
152 discipline_bit
= '/discipline/%d' % discipline
if discipline
!= 'all' else ''
153 region_bit
= match
.group(2) or ''
154 rest
= path
[match
.end():]
155 if not rest
.startswith('/recherche/'):
157 return discipline_bit
+ region_bit
+ rest
161 def apply(value
, func
):
162 """Applique une fonction arbitraire à la valeur filtrée."""
166 def getitem(container
, key
):
167 """Applique ``container[key]`` sur la valeur filtrée."""
168 return container
.get(key
, '')
171 # Snippet: http://djangosnippets.org/snippets/2237/
173 def query_string(parser
, token
):
175 Allows you too manipulate the query string of a page by adding and removing keywords.
176 If a given value is a context variable it will resolve it.
177 Based on similiar snippet by user "dnordberg".
181 TEMPLATE_CONTEXT_PROCESSORS = (
182 'django.core.context_processors.request',
185 to your django settings.
188 http://www.url.com/{% query_string "param_to_add=value, param_to_add=value" "param_to_remove, params_to_remove" %}
191 http://www.url.com/{% query_string "" "filter" %}filter={{new_filter}}
192 http://www.url.com/{% query_string "page=page_obj.number" "sort" %}
196 tag_name
, add_string
,remove_string
= token
.split_contents()
198 raise template
.TemplateSyntaxError
, "%r tag requires two arguments" % token
.contents
.split()[0]
199 if not (add_string
[0] == add_string
[-1] and add_string
[0] in ('"', "'")) or not (remove_string
[0] == remove_string
[-1] and remove_string
[0] in ('"', "'")):
200 raise template
.TemplateSyntaxError
, "%r tag's argument should be in quotes" % tag_name
202 add
= string_to_dict(add_string
[1:-1])
203 remove
= string_to_list(remove_string
[1:-1])
205 return QueryStringNode(add
,remove
)
207 class QueryStringNode(template
.Node
):
208 def __init__(self
, add
,remove
):
212 def render(self
, context
):
214 for k
, v
in context
["request"].GET
.items():
216 return get_query_string(p
,self
.add
,self
.remove
,context
)
218 def get_query_string(p
, new_params
, remove
, context
):
220 Add and remove query parameters. From `django.contrib.admin`.
226 for k
, v
in new_params
.items():
227 if k
in p
and v
is None:
232 for k
, v
in p
.items():
234 p
[k
] = template
.Variable(v
).resolve(context
)
238 return mark_safe('?' + '&'.join([u
'%s=%s' % (k
, v
) for k
, v
in p
.items()]).replace(' ', '%20'))
240 # Taken from lib/utils.py
241 def string_to_dict(string
):
246 if ',' not in string
:
247 # ensure at least one ','
249 for arg
in string
.split(','):
251 if arg
== '': continue
252 kw
, val
= arg
.split('=', 1)
256 def string_to_list(string
):
260 if ',' not in string
:
261 # ensure at least one ','
263 for arg
in string
.split(','):
265 if arg
== '': continue