- Author:
- JHsaunders
- Posted:
- October 20, 2010
- Language:
- Python
- Version:
- 1.2
- Score:
- 3 (after 3 ratings)
A template tag that includes a modified version of the GET query string. the query string can be manipulated by adding and removing fields. If a value is given that resolves to a context variable that the value of the variable is used. Based on this snippet by dnordberg, but with the ability to use context and done in a cleaner manner, without the need to add an arbitrary template.
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
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
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:
(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...)
#
django.http.QueryDict is your friend
#
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
#
Please login first before commenting.