Skip to content

Instantly share code, notes, and snippets.

@mrs83
Created August 26, 2013 21:56
Show Gist options
  • Save mrs83/6347156 to your computer and use it in GitHub Desktop.
Save mrs83/6347156 to your computer and use it in GitHub Desktop.
A Django Template tag used to construct urls with current querystring parameters. This is based on some code that I've written some years ago. Enjoy.
from django import template
from django.http import QueryDict
from django.utils.safestring import mark_safe
from django.template.loader import get_template
register = template.Library()
class QueryStringNode(template.Node):
def __init__(self, to_add, to_remove):
self.to_add = to_add
self.to_remove = to_remove
def render(self, context):
if 'request' not in context:
raise template.TemplateSyntaxError(
"'django.core.context_processors.request' not in TEMPLATE_CONTEXT_PROCESSORS"
)
querydict = context['request'].GET.copy()
return self.get_querystring(querydict, self.to_add, self.to_remove, context)
def parse_to_remove(self, to_remove):
if not to_remove:
return []
return [r.strip() for r in to_remove.strip('"').split(',')]
def parse_to_add(self, to_add):
kw = {}
to_add = to_add.strip('"')
if to_add == '':
return kw
for a in to_add.split(','):
k, v = a.strip().split('=')
kw[k] = v
return kw
def get_querystring(self, querydict, to_add, to_remove, context):
new_querydict = QueryDict(querydict.urlencode(), mutable=True)
try:
to_add = self.parse_to_add(to_add)
to_remove = self.parse_to_remove(to_remove)
except ValueError:
raise
raise template.TemplateSyntaxError("Unable to parse arguments")
for r in to_remove:
try:
del new_querydict[r]
except KeyError:
pass
for k, v in to_add.items():
if v.startswith('ctx:'):
v = v.replace('ctx:', '')
try:
value = template.Variable(v).resolve(context)
except template.VariableDoesNotExist:
value = None
if value:
new_querydict[k] = value
else:
new_querydict[k] = v
return new_querydict.urlencode()
@register.tag
def get_querystring(parser, token):
"""
First argument contains a list of variables that will be added to querystring.
If value starts with "ctx:", the value will be taken from template context::
{% get_querystring "pk=ctx:object.pk,a=1" %}
Second (optional) argument contains a list of variables that will be removed
from the querystring::
{% get_querystring "pk=ctx:object.pk,a=1" "b,c" %}
"""
bits = token.split_contents()
if len(bits) < 2:
raise template.TemplateSyntaxError("%s takes at least one argument" % bits[0])
to_add = bits[1]
try:
to_remove = bits[2]
except IndexError:
to_remove = None
return QueryStringNode(to_add, to_remove)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment