Manipulate URL query strings using context variables using a template tag

  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
from django import template
from django.utils.safestring import mark_safe
import datetime

register = template.Library()

@register.tag
def query_string(parser, token):
    """
    Allows you too manipulate the query string of a page by adding and removing keywords.
    If a given value is a context variable it will resolve it.
    Based on similiar snippet by user "dnordberg".
    
    requires you to add:
    
    TEMPLATE_CONTEXT_PROCESSORS = (
    'django.core.context_processors.request',
    )
    
    to your django settings. 
    
    Usage:
    http://www.url.com/{% query_string "param_to_add=value, param_to_add=value" "param_to_remove, params_to_remove" %}
    
    Example:
    http://www.url.com/{% query_string "" "filter" %}filter={{new_filter}}
    http://www.url.com/{% query_string "page=page_obj.number" "sort" %} 
    
    """
    try:
        tag_name, add_string,remove_string = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError, "%r tag requires two arguments" % token.contents.split()[0]
    if not (add_string[0] == add_string[-1] and add_string[0] in ('"', "'")) or not (remove_string[0] == remove_string[-1] and remove_string[0] in ('"', "'")):
        raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
    
    add = string_to_dict(add_string[1:-1])
    remove = string_to_list(remove_string[1:-1])
    
    return QueryStringNode(add,remove)

class QueryStringNode(template.Node):
    def __init__(self, add,remove):
        self.add = add
        self.remove = remove
        
    def render(self, context):
        p = {}
        for k, v in context["request"].GET.items():
            p[k]=v
        return get_query_string(p,self.add,self.remove,context)

def get_query_string(p, new_params, remove, context):
    """
    Add and remove query parameters. From `django.contrib.admin`.
    """
    for r in remove:
        for k in p.keys():
            if k.startswith(r):
                del p[k]
    for k, v in new_params.items():
        if k in p and v is None:
            del p[k]
        elif v is not None:
            p[k] = v
            
    for k, v in p.items():
        try:
            p[k] = template.Variable(v).resolve(context)
        except:
            p[k]=v
                
    return mark_safe('?' + '&'.join([u'%s=%s' % (k, v) for k, v in p.items()]).replace(' ', '%20'))

# Taken from lib/utils.py   
def string_to_dict(string):
    kwargs = {}
    
    if string:
        string = str(string)
        if ',' not in string:
            # ensure at least one ','
            string += ','
        for arg in string.split(','):
            arg = arg.strip()
            if arg == '': continue
            kw, val = arg.split('=', 1)
            kwargs[kw] = val
    return kwargs

def string_to_list(string):
    args = []
    if string:
        string = str(string)
        if ',' not in string:
            # ensure at least one ','
            string += ','
        for arg in string.split(','):
            arg = arg.strip()
            if arg == '': continue
            args.append(arg)
    return args

More like this

  1. Yet another query string template tag by atms 2 years, 1 month ago
  2. Updated - Template context debugger with (I)Pdb by dnordberg 3 years, 9 months ago
  3. Querystring Builder - create urls with GET params by jibberia 2 years, 4 months ago
  4. HTTPS redirections middleware with updated URL template tag by xlq 7 months ago
  5. Modify query string on a url by dnordberg 4 years, 11 months ago

Comments

mattwestcott (on November 27, 2010):

Very useful snippet, but as it stands it's vulnerable to a cross-site scripting attack (because the URL variables previously provided by the user are passed through mark_safe with no escaping, apart from replacing space characters). This can be fixed by adding 'import urllib' at the top, and changing line 73 to:

return mark_safe('?' + '&'.join([u'%s=%s' % (urllib.quote_plus(str(k)), urllib.quote_plus(str(v))) for k, v in p.items()]))

(Also, to be completely correct even when autoescaping is turned off, I suspect it should be using a plain '&' to delimit the arguments and passing it back as an unsafe string for the template layer to escape - but I'll leave that for someone else to confirm...)

#

altaurog (on August 8, 2011):

django.http.QueryDict is your friend

#

jsilva (on October 22, 2011):

How can I pass a python variable within a double quoted argument of the template tag?

Im trying to create the paginator links, next, previous, etc.. In the query string I might have different parameters apart from "page" and thus to iterate from pages I want to modify only this parameter in the query string.. Something like this:

<a href="{% query_string "page={{ next }}" "page" %}"> Next </a>

which obviously doesnt work since django interprets what is inside double quotes as literal string, so it doesnt resolve the variable's value.

How can I do this? Do I need to change the templatetag and send an extra argument (the page variable) ?

Cheers

#

akaihola (on October 19, 2012):

Here's a list of other implementations I could find for a Django template tag which modifies the current HTTP GET query string.

On djangosnippets.org:

On Stack Overflow:

On PyPI:

On GitHub:

#

siblek31 (on April 13, 2013):

sistem Universitas Kuliah di Fakultas Teknik Biomedis, CTU di Praha.

Universitas tips cepat hamil pendidikan soal ulangan sd meliputi pengajaran, penelitian, dan kegiatan pelayanan sosial, dan itu termasuk tingkat sarjana (kadang-kadang disebut sebagai pendidikan tinggi) dan pascasarjana (atau pascasarjana) kursus teknisi komputer tingkat (kadang-kadang disebut sebagai sekolah pascasarjana). Universitas umumnya terdiri dari beberapa perguruan tinggi. Di Amerika Serikat, perguruan tinggi kursus bahasa inggris murah dapat menjadi pribadi dan independen, seperti Universitas Yale, mereka dapat umum dan Negara diatur, seperti Pennsylvania State Sistem Pendidikan Tinggi, atau mereka dapat mandiri tetapi Negara didanai, cara mendapatkan uang dari internet seperti University of Virginia.

#

(Forgotten your password?)