Skip to content

Commit

Permalink
Create a class to manipulate the parameters and build the url. Add ++…
Browse files Browse the repository at this point in the history
… and -- operators.
  • Loading branch information
rlopezcc committed Jan 26, 2017
1 parent 8c6303a commit e105d70
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 16 deletions.
63 changes: 48 additions & 15 deletions qurl_templatetag/templatetags/qurl.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ def qurl(parser, token):
name=None: remove all values of name
name+=value: append a new value for name
name-=value: remove the value of name with the value
name++: increment value by one
name--: decrement value by one
Example::
Expand All @@ -56,7 +58,7 @@ def qurl(parser, token):

qs = []
if len(bits):
kwarg_re = re.compile(r'(\w+)(\-=|\+=|=)(.*)')
kwarg_re = re.compile(r'(\w+)(\-=|\+=|=|\+\+|\-\-)(.*)')
for bit in bits:
match = kwarg_re.match(bit)
if not match:
Expand All @@ -67,6 +69,41 @@ def qurl(parser, token):
return QURLNode(url, qs, asvar)


class Qurl(object):

def __init__(self, url):
self.url = url
self.qsl = parse_qsl(urlparse(url).query)

def set(self, name, value):
if django.VERSION[0] <= 1 and django.VERSION[1] <= 4:
value = value or None
self.qsl = [(q, v) for (q, v) in self.qsl if q != name]
if value is not None:
self.qsl.append((name, value))

def add(self, name, value):
self.qsl = [p for p in self.qsl if not(p[0] == name and p[1] == value)]
self.qsl.append((name, value,))

def remove(self, name, value):
self.qsl = [qb for qb in self.qsl if qb != (name, str(value))]

def inc(self, name, value=1):
self.qsl = [(q, v) if q != name else (q, int(v) + value)
for (q, v) in self.qsl]
if name not in dict(self.qsl).keys():
self.qsl.append((name, value))

def dec(self, name, value=1):
self.inc(name, -value)

def get(self):
parsed = list(urlparse(self.url))
parsed[4] = urlencode(self.qsl)
return urlunparse(parsed)


@register.tag
def rqurl(parser, token):
return qurl(parser, token, True)
Expand All @@ -81,28 +118,24 @@ def __init__(self, url, qs, asvar):
self.asvar = asvar

def render(self, context):
url = self.url.resolve(context)
urlp = list(urlparse(url))
qp = parse_qsl(urlp[4])
render_qurl = Qurl(self.url.resolve(context))

for name, op, value in self.qs:
name = smart_str(name)
value = value.resolve(context)
value = smart_str(value) if value is not None else None
if op == '+=':
qp = [p for p in qp if not(p[0] == name and p[1] == value)]
qp.append((name, value,))
render_qurl.add(name, value)
elif op == '-=':
qp = [p for p in qp if not(p[0] == name and p[1] == value)]
render_qurl.remove(name, value)
elif op == '=':
if django.VERSION[0] <= 1 and django.VERSION[1] <= 4:
value = value or None
qp = [p for p in qp if not(p[0] == name)]
if value is not None:
qp.append((name, value,))

urlp[4] = urlencode(qp, True)
url = urlunparse(urlp)
render_qurl.set(name, value)
elif op == '++':
render_qurl.inc(name)
elif op == '--':
render_qurl.dec(name)

url = render_qurl.get()
if self.asvar:
context[self.asvar] = url
return ''
Expand Down
81 changes: 80 additions & 1 deletion tests/test_qurl_templatetag.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@


from django.test import TestCase
from django.template import Template, Context
from django.template import Template, Context, TemplateSyntaxError
from qurl_templatetag.templatetags.qurl import Qurl


class QUrlTemplateTagTestCase(TestCase):
Expand All @@ -36,3 +37,81 @@ def test_qurl_as(self):
'{% qurl "http:https://sophilabs.com/?a=1" a=None as url %}'
).render(context)
self.assertEqual(context.get('url'), 'http:https://sophilabs.com/')

def test_qurl_inc(self):
out = Template(
'{% load qurl %}'
'{% qurl "http:https://sophilabs.com/?a=1" a++ %}'
).render(Context())
self.assertEqual(out, 'http:https://sophilabs.com/?a=2')

out = Template(
'{% load qurl %}'
'{% qurl "http:https://sophilabs.com/?a=1" b++ %}'
).render(Context())
self.assertEqual(out, 'http:https://sophilabs.com/?a=1&b=1')

def test_qurl_dec(self):
out = Template(
'{% load qurl %}'
'{% qurl "http:https://sophilabs.com/?a=1" a-- %}'
).render(Context())
self.assertEqual(out, 'http:https://sophilabs.com/?a=0')

out = Template(
'{% load qurl %}'
'{% qurl "http:https://sophilabs.com/?a=1" b-- %}'
).render(Context())
self.assertEqual(out, 'http:https://sophilabs.com/?a=1&b=-1')

def test_malformed(self):
template = """
{% load qurl %}
{% qurl "http:https://sophilabs.com/?a=1" a**2 %}
"""
self.assertRaises(TemplateSyntaxError, Template, template)


class QurlTestCase(TestCase):

def test_set(self):
qurl = Qurl('http:https://sophilabs.com/?a=1')

qurl.set('a', 2)
self.assertEqual(qurl.get(), 'http:https://sophilabs.com/?a=2')

qurl.set('b', 1)
self.assertEqual(qurl.get(), 'http:https://sophilabs.com/?a=2&b=1')

qurl.set('a', 3)
self.assertEqual(qurl.get(), 'http:https://sophilabs.com/?b=1&a=3')

def test_add(self):
qurl = Qurl('http:https://sophilabs.com/?a=1')

qurl.add('a', 2)
self.assertEqual(qurl.get(), 'http:https://sophilabs.com/?a=1&a=2')

qurl.add('b', 9)
self.assertEqual(qurl.get(), 'http:https://sophilabs.com/?a=1&a=2&b=9')

def test_remove(self):
qurl = Qurl('http:https://sophilabs.com/?a=1&a=3')

qurl.remove('a', 3)
self.assertEqual(qurl.get(), 'http:https://sophilabs.com/?a=1')

def test_inc(self):
qurl = Qurl('http:https://sophilabs.com/?a=1')

qurl.inc('a', 1)
self.assertEqual(qurl.get(), 'http:https://sophilabs.com/?a=2')

qurl.inc('b', 1)
self.assertEqual(qurl.get(), 'http:https://sophilabs.com/?a=2&b=1')

def test_dec(self):
qurl = Qurl('http:https://sophilabs.com/?a=4')

qurl.dec('a', 1)
self.assertEqual(qurl.get(), 'http:https://sophilabs.com/?a=3')

0 comments on commit e105d70

Please sign in to comment.