Templatetag for generating query strings based on the current request query string

  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
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
"""
Templatetags for generating query string modifying the current request's query
string.

version: 0.2

"""
from django import template
from django.utils.datastructures import MultiValueDict


register = template.Library()


def _unquote(str, required=True, error_msg=''):
    """
    Strips the quotes from a string, I find it useful after parsing tags with
    split_contents().

    """
    if str[0] == str[-1] and str[0] in ('"',"'"):
        return str[1:-1]
    else:
        if required:
            raise TemplateSyntaxError, error_msg
        return str


def dict_from_qstring(qstring):
    """
    Returns a MultiValueDict from a query string.

    """
    mvd = MultiValueDict()
    for item in qstring.split('&'):
        sp = item.split('=')
        if len(sp) == 1:
            value = None
        elif len(sp) == 2:
            value = sp[1]
        else:
            continue
        mvd.appendlist(sp[0], value)
    return mvd


def qstring_from_dict(mvd):
    """
    Returns a query string from a MultiValueDict.

    """
    tmp = []
    for key, values in mvd.lists():
        for value in values:
            tmp.append('='.join([key, str(value)]))
    return '&'.join(tmp)


def tag_from_operation(operation_fn):
    """
    Returns a tag function wich uses a operation function (operation_fn).

    """
    class Node(template.Node):
        def __init__(self, qstring):
            self.qstring = qstring

        def render(self, context):
            mvd = dict_from_qstring(self.qstring)
            diff_mvd = operation_fn(context['request'].GET, mvd)
            return qstring_from_dict(diff_mvd)

    def do_operation(parser, token):
        args = token.split_contents()
        tag_name = args[0]
        qstring = _unquote(args[1], required=True,
                           error_msg='%r tag\'s argument should '
                                     'be in quotes.' % tag_name)
        return Node(qstring)
    return do_operation


def delete(lmvd, rmvd):
    mvd = lmvd.copy()
    for key, value in rmvd.lists():
        if key in mvd:
            if None in value:
                new_list = []
            else:
                new_list = [i for i in mvd.getlist(key) if i not in value]
            mvd.setlist(key, new_list)
    return mvd

register.tag('qs_delete', tag_from_operation(delete))


def update(lmvd, rmvd):
    mvd = lmvd.copy()
    for key, values in rmvd.lists():
        if key in mvd:
            mvd.setlist(key, values)
    return mvd

register.tag('qs_update', tag_from_operation(update))

Comments

(Forgotten your password?)

You may use Markdown syntax here, but raw HTML will be removed.