[Django]-How do I construct a Django reverse/url using query args?

21πŸ‘

βœ…

Your regular expresion has no place holders (that’s why you are getting NoReverseMatch):

url(r'^depict$', cyclops.django.depict, name="cyclops-depict"),

You could do it like this:

{% url cyclops-depict %}?smiles=CO&width=200&height=200

URLconf search does not include GET or POST parameters

Or if you wish to use {% url %} tag you should restructure your url pattern to something like

r'^depict/(?P<width>\d+)/(?P<height>\d+)/(?P<smiles>\w+)$' 

then you could do something like

{% url cyclops-depict 200 200 "CO" %}

Follow-up:

Simple example for custom tag:

from django.core.urlresolvers import reverse
from django import template
register = template.Library()

@register.tag(name="myurl")
def myurl(parser, token):
    tokens = token.split_contents()
    return MyUrlNode(tokens[1:])

class MyUrlNode(template.Node):
    def __init__(self, tokens):
        self.tokens = tokens
    def render(self, context):
        url = reverse('cyclops-depict')
        qs = '&'.join([t for t in self.tokens])
        return '?'.join((url,qs))

You could use this tag in your templates like so:

{% myurl width=200 height=200 name=SomeName %}

and hopefully it should output something like

/depict?width=200&height=200&name=SomeName
πŸ‘€Davor Lucic

57πŸ‘

Building an url with query string by string concatenation as suggested by some answers is as bad idea as building SQL queries by string concatenation. It is complicated, unelegant and especially dangerous with a user provided (untrusted) input. Unfortunately Django does not offer an easy possibility to pass query parameters to the reverse function.

Python standard urllib however provides the desired query string encoding functionality.

In my application I’ve created a helper function:

def url_with_querystring(path, **kwargs):
    return path + '?' + urllib.urlencode(kwargs) # for Python 3, use urllib.parse.urlencode instead

Then I call it in the view as follows:

quick_add_order_url = url_with_querystring(reverse(order_add),
    responsible=employee.id, scheduled_for=datetime.date.today(),
    subject='hello world!')
# http://localhost/myapp/order/add/?responsible=5&
#     scheduled_for=2011-03-17&subject=hello+world%21

Please note the proper encoding of special characters like space and exclamation mark!

πŸ‘€geekQ

19πŸ‘

I recommend to use builtin django’s QueryDict. It also handles lists properly. End automatically escapes some special characters (like =, ?, /, β€˜#’):

from django.http import QueryDict
from django.core.urlresolvers import reverse

q = QueryDict('', mutable=True)
q['some_key'] = 'some_value'
q.setlist('some_list', [1,2,3])
'%s?%s' % (reverse('some_view_name'), q.urlencode())
# '/some_url/?some_list=1&some_list=2&some_list=3&some_key=some_value'

q.appendlist('some_list', 4)
q['value_with_special_chars'] = 'hello=w#rld?'
'%s?%s' % (reverse('some_view_name'), q.urlencode())
# '/some_url/?value_with_special_chars=hello%3Dw%23rld%3F&some_list=1&some_list=2&some_list=3&some_list=4&some_key=some_value'

To use this in templates you will need to create custom template tag

πŸ‘€imposeren

7πŸ‘

Working variation of previous answers and my experience with dealing this stuff.

from django.urls import reverse
from django.utils.http import urlencode

def build_url(*args, **kwargs):
    params = kwargs.pop('params', {})
    url = reverse(*args, **kwargs)
    if params:
        url += '?' + urlencode(params)
    return url

How to use:

>>> build_url('products-detail', kwargs={'pk': 1}, params={'category_id': 2})
'/api/v1/shop/products/1/?category_id=2'

5πŸ‘

The answer that used urllib is indeed good, however while it was trying to avoid strings concatenation, it used it in path + '?' + urllib.urlencode(kwargs). I believe this may create issues when the path has already some query parmas.

A modified function would look like:

def url_with_querystring(url, **kwargs):
    url_parts = list(urlparse.urlparse(url))
    query = dict(urlparse.parse_qsl(url_parts[4]))
    query.update(kwargs)
    url_parts[4] = urllib.urlencode(query)
    return urlparse.urlunparse(url_parts)
πŸ‘€Nour Wolf

4πŸ‘

Neither of the original answers addresses the related issue resolving URLs in view code. For future searchers, if you are trying to do this, use kwargs, something like:

reverse('myviewname', kwargs={'pk': value})
πŸ‘€Aitch

Leave a comment