Created
January 15, 2012 05:59
-
-
Save tkaemming/1614638 to your computer and use it in GitHub Desktop.
querystring template tag helpers for django
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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