-
-
Save jpadilla/6081538 to your computer and use it in GitHub Desktop.
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
""" | |
qurl is a tag to append, remove or replace query string parameters from an url | |
https://gist.github.com/pricco/3714115 | |
""" | |
import re | |
from django.template import Library, Node, TemplateSyntaxError | |
from urlparse import urlparse, parse_qsl, urlunparse | |
from django.utils.encoding import smart_str | |
from urllib import urlencode | |
register = Library() | |
@register.tag | |
def qurl(parser, token): | |
""" | |
Append, remove or replace query string parameters from an url (preserve order) | |
{% qurl url [param]* [as <var_name>] %} | |
param: | |
name=value: replace all values of name by one value | |
name=None: remove all values of name | |
name+=value: append a new value for name | |
name-=value: remove the value of name with the value | |
Example:: | |
{% qurl '/search?page=1&color=blue&color=green' order='name' page=None color+='red' color-='green' %} | |
Output: /search?color=blue&order=name&color=red | |
{% qurl request.get_full_path order='name' %} | |
""" | |
bits = token.split_contents() | |
if len(bits) < 2: | |
raise TemplateSyntaxError("'%s' takes at least one argument (url)" % bits[0]) | |
url = parser.compile_filter(bits[1]) | |
asvar = None | |
bits = bits[2:] | |
if len(bits) >= 2 and bits[-2] == 'as': | |
asvar = bits[-1] | |
bits = bits[:-2] | |
qs = [] | |
if len(bits): | |
kwarg_re = re.compile(r"(\w+)(\-=|\+=|=)(.+)") | |
for bit in bits: | |
match = kwarg_re.match(bit) | |
if not match: | |
raise TemplateSyntaxError("Malformed arguments to url tag") | |
name, op, value = match.groups() | |
qs.append((name, op, parser.compile_filter(value),)) | |
return QURLNode(url, qs, asvar) | |
class QURLNode(Node): | |
"""Implements the actions of the qurl tag.""" | |
def __init__(self, url, qs, asvar): | |
self.url = url | |
self.qs = qs | |
self.asvar = asvar | |
def render(self, context): | |
urlp = list(urlparse(self.url.resolve(context))) | |
qp = parse_qsl(urlp[4]) | |
for name, op, value in self.qs: | |
name = smart_str(name) | |
value = smart_str(value.resolve(context)) | |
if op == '+=': | |
qp.append((name, value,)) | |
elif op == '-=': | |
qp = filter(lambda (n, v): not(n == name and v == value), qp) | |
elif op == '=': | |
qp = filter(lambda (n, v): not(n == name), qp) | |
if value is not None and value != 'None': | |
qp.append((name, value,)) | |
urlp[4] = urlencode(qp, True) | |
url = urlunparse(urlp) | |
if self.asvar: | |
context[self.asvar] = url | |
return '' | |
else: | |
return url |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment