Last active
October 28, 2018 07:03
-
-
Save etchalon/4493752 to your computer and use it in GitHub Desktop.
Query String alteration template tag for Django.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Query String manipulation filters | |
""" | |
import logging | |
from django import template | |
from django.http import QueryDict | |
from django.utils.translation import ugettext as _ | |
register = template.Library() | |
class QueryStringAlterer(template.Node): | |
""" | |
Query String alteration template tag | |
Receives a query string (either text or a QueryDict such as request.GET) | |
and a list of changes to apply. The result will be returned as text query | |
string, allowing use like this:: | |
<a href="?{% qs_alter request.GET type=object.type %}">{{ label }}</a> | |
There are four available alterations: | |
Assignment: | |
name=var | |
Deletion - removes the named parameter: | |
-name | |
Appending (treating the qstring as a list): | |
name+=var | |
Removing (treating the qstring as a list): | |
name-=var | |
Examples: | |
Query string provided as QueryDict:: | |
{% qs_alter request.GET foo=bar %} | |
{% qs_alter request.GET foo=bar baaz=quux %} | |
{% qs_alter request.GET foo+=bar %} | |
{% qs_alter request.GET foo-=bar %} | |
{% qs_alter request.GET foo=bar baaz+=quux -corge %} | |
Query string provided as string:: | |
{% qs_alter "foo=baaz" foo=bar %}"> | |
""" | |
def __init__(self, base_qs, *args): | |
self.base_qs = template.Variable(base_qs) | |
self.args = args | |
def render(self, context): | |
base_qs = self.base_qs.resolve(context) | |
if isinstance(base_qs, QueryDict): | |
qs = base_qs.copy() | |
else: | |
qs = QueryDict(base_qs, mutable=True) | |
for arg in self.args: | |
# look for += (add to assumed list or concat to string) | |
if arg.find('+=') > -1: | |
k,v = arg.split("+=", 2) | |
value = template.Variable(v).resolve(context) | |
if k in qs: | |
qs[k] = '%s,%s' % (qs[k],str(value)) | |
else: | |
qs[k] = str(value) | |
# look for -= (remove from assumed list or string) | |
elif arg.find('-=') > -1: | |
k,v = arg.split("-=", 2) | |
value = template.Variable(v).resolve(context) | |
if k in qs: | |
ql = qs[k].split(',') | |
if str(value) in ql: | |
ql.remove(str(value)) | |
if len(ql) > 0: | |
qs[k] = ','.join(ql) | |
else: | |
del qs[k] | |
# look for just = (set, overriding existing value if it exists) | |
elif arg.find('=') > -1: | |
k, v = arg.split("=", 2) | |
if k in qs: | |
qs[k] = template.Variable(v).resolve(context) | |
else: | |
qs[k] = template.Variable(v).resolve(context) | |
# look for just - (remove from dict) | |
elif arg.find('-') > -1: | |
k, v = arg.split("-", 2) | |
if k in qs: | |
del qs[k] | |
return qs.urlencode(safe=',') | |
@classmethod | |
def qs_alter_tag(cls, parser, token): | |
try: | |
bits = token.split_contents() | |
except ValueError: | |
raise template.TemplateSyntaxError( | |
_('qs_alter requires at least two arguments: the initial query string and at least one alteration') | |
) | |
return QueryStringAlterer(bits[1], *bits[2:]) | |
register.tag('qs_alter', QueryStringAlterer.qs_alter_tag) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment