Url query string template tag (qurl)

 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

  1. Yet another query string template tag by atms 3 years ago
  2. Manipulate URL query strings using context variables using a template tag by JHsaunders 3 years, 6 months ago
  3. Modify query string on a url by dnordberg 5 years, 10 months ago
  4. URL Query Parameter Menu by drg006 6 years, 11 months ago
  5. Url persistance of GET variables by alex_ndc 5 years, 5 months ago

Comments

(Forgotten your password?)