2 Allows setting/changing/removing of chosen url query string parameters, while
3 maintaining any existing others.
5 Expects the current request to be available in the context as ``request``.
9 {% set_url_param page=next_page %}
10 {% set_url_param page="" %}
11 {% set_url_param filter="books" page=1 %}
17 from django import template
18 from django.template.loader import get_template
19 from django.utils.safestring import mark_safe
22 register = template.Library()
25 class SetUrlParamNode(template.Node):
26 def __init__(self, changes):
27 self.changes = changes
29 def render(self, context):
30 request = context.get('request', None)
33 # Note that we want params to **not** be a ``QueryDict`` (thus we
34 # don't use it's ``copy()`` method), as it would force all values
35 # to be unicode, and ``urllib.urlencode`` can't handle that.
36 params = dict(request.GET)
37 for key, newvalue in self.changes.items():
38 newvalue = newvalue.resolve(context)
39 if newvalue == '' or newvalue is None:
40 params.pop(key, False)
42 params[key] = unicode(newvalue)
44 # ``urlencode`` chokes on unicode input, so convert everything to utf8.
45 # Note that if some query arguments passed to the site have their
46 # non-ascii characters screwed up when passed though this, it's most
47 # likely not our fault. Django (the ``QueryDict`` class to be exact)
48 # uses your projects DEFAULT_CHARSET to decode incoming query strings,
49 # whereas your browser might encode the url differently. For example,
50 # typing "ä" in my German Firefox's (v2) address bar results in "%E4"
51 # being passed to the server (in iso-8859-1), but Django might expect
52 # utf-8, where ä would be "%C3%A4"
54 if isinstance(s, list):
57 return s.encode('utf-8') if isinstance(s, unicode) else s
58 params = dict([(mkstr(k), mkstr(v)) for k, v in params.items()])
59 # done, return (string is already safe)
60 return '?' + urllib.urlencode(params, doseq=True)
64 def set_url_param(parser, token):
65 bits = token.contents.split()
69 a, b = i.split('=', 1)
72 a_line_iter = StringIO.StringIO(a).readline
73 keys = list(tokenize.generate_tokens(a_line_iter))
74 if keys[0][0] == tokenize.NAME:
75 # workaround bug #5270
76 b = (template.Variable(b) if b == '""' else
77 parser.compile_filter(b))
82 raise (template.TemplateSyntaxError,
83 "Argument syntax wrong: should be key=value")
84 return SetUrlParamNode(qschanges)
87 class RenderTableNode(template.Node):
88 def __init__(self, table_var_name):
89 self.table_var = template.Variable(table_var_name)
91 def render(self, context):
92 table = self.table_var.resolve(context)
93 request = context.get('request', None)
94 context = template.Context({'request': request, 'table': table})
96 table.request = request
97 return get_template('django_tables/table.html').render(context)
104 def render_table(parser, token):
106 _, table_var_name = token.contents.split()
108 raise template.TemplateSyntaxError,\
109 "%r tag requires a single argument" % token.contents.split()[0]
110 return RenderTableNode(table_var_name)