Skip to content

Instantly share code, notes, and snippets.

@tkaemming
Created January 15, 2012 05:59
Show Gist options
  • Save tkaemming/1614638 to your computer and use it in GitHub Desktop.
Save tkaemming/1614638 to your computer and use it in GitHub Desktop.
querystring template tag helpers for django
from copy import copy
from urllib import urlencode
from urlparse import parse_qs, urlparse, urlunparse
from django import template
register = template.Library()
@register.filter
def with_querystring(value, request):
"""
Appends the provided request's querystring to a specified URL.
This can be helpful when used as a block filter, such as:
{% filter with_querystring:request %}{% url 'search' %}{% endfilter %}
or, on model attributes:
{{ model.url|with_querystring:request }}.
It's especially helpful when paired with the built in Django request
context processor located in `django.core.context_processors.request`.
"""
current_bits = urlparse(request.get_full_path())
current_query = parse_qs(current_bits.query)
value_bits = urlparse(value)
value_query = parse_qs(value_bits.query)
merged_query = copy(current_query)
merged_query.update(value_query)
value_list = list(value_bits)
value_list[4] = urlencode(merged_query, doseq=True)
return urlunparse(value_list)
@register.tag
def withquery(parser, token):
"""
Wraps a URL and preserves the specified query variables.
For example, if you wanted to preserve the 'cause' query string parameter:
{% withquery 'cause' %}/{% endwithquery %}
"""
bits = token.split_contents()
variables = bits[1:] # Ignore the first position, since it's the tag name.
nodelist = parser.parse(('endwithquery',))
parser.delete_first_token()
return QueryStringPreserverNode(nodelist, variables)
class QueryStringPreserverNode(template.Node):
def __init__(self, nodelist, variables):
self.nodelist = nodelist
self.variables = [template.Variable(variable) for variable in variables]
def render(self, context):
request = context['request']
rendered = self.nodelist.render(context)
preserve_fields = [variable.resolve(context) for variable in
self.variables]
current_parsed_url = urlparse(request.get_full_path())
current_query = parse_qs(current_parsed_url.query)
rendered_parsed_url = urlparse(rendered)
rendered_query = parse_qs(rendered_parsed_url.query)
# Select only those we've explicitly asked to preserve...
preserved_query = dict([(name, value) for name, value in
current_query.items() if name in preserve_fields])
preserved_query.update(rendered_query)
rendered_list = list(rendered_parsed_url)
rendered_list[4] = urlencode(preserved_query, doseq=True)
return urlunparse(rendered_list)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment