I'm using Django 0.96 for a project, and the url tag does not have all the capabilities I need.
I want a way to persist all or some of the GET parameters between requests. I also want a way to add to the current url a list of extra parameters, or nullify certain parameters.
In this snippet I am defining 2 tags ... link_persist and link_add. It only works with Django 0.96, as the API changed ... but maybe a good soul can fix it for 1.0, as I haven't had any time available.
A tip for usage: if you specify a parameter as being the empty string, or None, the parameter will be removed from the link. When you specify a parameter already available in GET, it will replace it.
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 105 106 107 108 109 110 | from django.core.urlresolvers import reverse
from django.template import FilterExpression
from django.template import Library, Node, TemplateSyntaxError, resolve_variable
from re import split
from urllib import quote,unquote
import re
register = Library()
class LinkNode(Node):
def __init__(self, viewname, args, kwargs, add_to_current_link=False):
self.viewname = viewname
self.kwargs = kwargs
self.args = args
self.add_to_current_link = add_to_current_link
def render(self,context):
req = resolve_variable('request',context)
args = [isinstance(k,FilterExpression) and k.resolve(context) or k for k in self.args]
kwargs = req.GET.copy()
for k,v in self.kwargs.items():
if isinstance(v, FilterExpression) and v.token:
kwargs[k] = v.resolve(context)
elif v:
kwargs[k] = v
try:
url = not self.add_to_current_link and reverse(viewname=self.viewname, args=args, kwargs=None) or req.path
except:
url = req.path
# check to see if named arguments have been passed
query_started = url.find('?') > -1
query_string = ""
raw_url = unquote(url)
for k,values in kwargs.items():
if not isinstance(values,list):
values = [values]
params_added = "&".join(
[quote(k) + "=" + quote(isinstance(v,str) and v or str(v)) for v in values
if v and (not query_started or not re.search(r"\b" + re.escape(k + "=" + v) + r"\b", raw_url))])
if params_added: query_string += "&" + params_added
if not query_started and len(query_string) > 0:
query_string = "?" + query_string[1:]
return url + query_string
def link_persist(parser, token):
"""Url Tag that persists GET variables
It has the same behaviour as the standard url tag
found in django.template.defaulttags.
But GET variables are passed by default to the 'reverse' url
method that builds the final url. Specified parameters override
GET parameters.
Usage: {% link_persist viewname arg1, arg2, ... karg1=val1, karg2=val2 ... %}
This has been tested with Django version 0.96"""
bits = token.contents.split(' ', 2)
if len(bits) < 2:
raise TemplateSyntaxError, "'%s' takes at least one argument (path to a view)" % bits[0]
args = []
kwargs = {}
if len(bits) > 2:
for arg in bits[2].split(','):
if '=' in arg:
k, v = arg.split('=', 1)
kwargs[k] = parser.compile_filter(v)
else:
args.append(parser.compile_filter(arg))
return LinkNode(bits[1], args, kwargs)
def link_add(parser, token):
"""Tag that adds parameters to the current url.
Usage: {% link_add karg1=val1, karg2=val2 ... %}
This has been tested with Django version 0.96"""
bits = token.contents.split(' ', 2)
args = []
kwargs = {}
if len(bits) > 1:
for arg in bits[1].split(','):
if '=' in arg:
k, v = arg.split('=', 1)
kwargs[k] = parser.compile_filter(v)
return LinkNode(None, args, kwargs, True)
register.tag('link_persist', link_persist)
register.tag('link_add', link_add)
|
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, 8 months ago
Comments
That looks a bit complicated for something that should be so simple. I use this, which works for all my purposes:
It works great for dealing with paged content:
#
That's cool, although my needs a little more complicated.
I'll work on simplifying it ... my python-foo is a little rusty :)
#
I used this snippet for quite some time and finally found a bug :-)
You have the following line in the LinkNode:
for k,values in kwargs.items():
but it must be:
for k,values in kwargs.lists():
otherwise you will only get the last value for each key.
#
Please login first before commenting.