3 from django import template
4 from django.utils.html import escape
7 register = template.Library()
10 class QueryStringNode(template.Node):
16 OPERATORS = [REPLACE, APPEND, REMOVE, PURGE]
18 op_regex = re.compile('|'.join(map(re.escape, OPERATORS)))
20 def __init__(self, tag_name, parsed_args):
21 self.tag_name = tag_name
22 self.parsed_args = parsed_args
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.
30 query_dict = context['request'].GET.copy()
34 for key, op, value in self.parsed_args:
35 key = key.resolve(context)
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
45 query_dict.getlist(key).remove(value.resolve(context))
48 elif op == self.PURGE:
49 # item!: Completely remove from current query arguments.
50 # e.g. item=1&item=2 -> ''
56 # item=1: Replace current query arguments, e.g. item=2 -> item=1
57 query_dict[key] = value.resolve(context)
59 qs = query_dict.urlencode()
60 return '?' + escape(qs) if qs else ''
64 def query_string(parser, token):
65 # {% query_string page=1 size! item+="foo" item-="bar" %}
66 args = token.split_contents()
72 for pair in raw_pairs:
74 key, value = QueryStringNode.op_regex.split(pair, 1)
76 raise template.TemplateSyntaxError("{} tag's argument should be in format foo({})bar".format(
77 tag_name, '|'.join(QueryStringNode.OPERATORS)))
80 (parser.compile_filter(key), QueryStringNode.op_regex.search(pair).group(), parser.compile_filter(value)))
82 return QueryStringNode(tag_name, parsed_args)