qurl is a tag to append, remove or replace query string parameters from an url (preserve order)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | """qurl is a tag to append, remove or replace query string parameters from an url (preserve order)"""
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 = value.resolve(context)
value = smart_str(value) if value is not None else None
if op == '+=':
qp = filter(lambda (n, v): not(n == name and v == value), qp)
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:
qp.append((name, value,))
urlp[4] = urlencode(qp, True)
url = urlunparse(urlp)
if self.asvar:
context[self.asvar] = url
return ''
else:
return url
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
Please login first before commenting.