fix in handling file name with special characters
[qcg-portal.git] / qcg / templatetags / query_string.py
1 import re
2
3 from django import template
4 from django.utils.html import escape
5
6
7 register = template.Library()
8
9
10 class QueryStringNode(template.Node):
11     REPLACE = '='
12     APPEND = '+='
13     REMOVE = '-='
14     PURGE = '!'
15
16     OPERATORS = [REPLACE, APPEND, REMOVE, PURGE]
17
18     op_regex = re.compile('|'.join(map(re.escape, OPERATORS)))
19
20     def __init__(self, tag_name, parsed_args):
21         self.tag_name = tag_name
22         self.parsed_args = parsed_args
23
24     def render(self, context):
25         # django.core.context_processors.request should be enabled in
26         # settings.TEMPLATE_CONTEXT_PROCESSORS.
27         # Or else, directly pass the HttpRequest object as 'request' in context.
28
29         try:
30             query_dict = context['request'].GET.copy()
31         except KeyError:
32             return ''
33
34         for key, op, value in self.parsed_args:
35             key = key.resolve(context)
36
37             if op == self.APPEND:
38                 # item+="foo": Append to current query arguments.
39                 # e.g. item=1 -> item=1&item=foo
40                 query_dict.appendlist(key, value.resolve(context))
41             elif op == self.REMOVE:
42                 # item-="bar": Remove from current query arguments.
43                 # e.g. item=1&item=bar -> item=1
44                 try:
45                     query_dict.getlist(key).remove(value.resolve(context))
46                 except KeyError:
47                     pass
48             elif op == self.PURGE:
49                 # item!: Completely remove from current query arguments.
50                 # e.g. item=1&item=2 -> ''
51                 try:
52                     del query_dict[key]
53                 except KeyError:
54                     pass
55             else:
56                 # item=1: Replace current query arguments, e.g. item=2 -> item=1
57                 query_dict[key] = value.resolve(context)
58
59         qs = query_dict.urlencode()
60         return '?' + escape(qs) if qs else ''
61
62
63 @register.tag
64 def query_string(parser, token):
65     # {% query_string page=1 size! item+="foo" item-="bar" %}
66     args = token.split_contents()
67
68     tag_name = args[0]
69     raw_pairs = args[1:]
70
71     parsed_args = []
72     for pair in raw_pairs:
73         try:
74             key, value = QueryStringNode.op_regex.split(pair, 1)
75         except:
76             raise template.TemplateSyntaxError("{} tag's argument should be in format foo({})bar".format(
77                 tag_name, '|'.join(QueryStringNode.OPERATORS)))
78
79         parsed_args.append(
80             (parser.compile_filter(key), QueryStringNode.op_regex.search(pair).group(), parser.compile_filter(value)))
81
82     return QueryStringNode(tag_name, parsed_args)