Including a querystring in a django.core.urlresolvers reverse() call
I'm trying to reverse a named URL and include a querystring in it. Basically, I've modified the login function, and I want to send ?next=
in it.
Here's what I'm doing now: reverse(name) + "?next=" + reverse(redirect)
Here's what I'd like to do: reverse(name, kwargs = { 'next':reverse(redirect) } )
My URL for the login page (just as an example) looks like this:
url(r'^login/', custom_login, name = 'login'),
So how do I modify this whole thing (or call it) to include the next without having to concatenate it? It feels like an iffy solution at best.
Solution 1:
You can't capture GET parameters in the url confs, so your method is correct.
I generally prefer string formatting but it's the same thing."%s?next=%s" % (reverse(name), reverse(redirect))
http://docs.djangoproject.com/en/dev/topics/http/urls/#what-the-urlconf-searches-against
The URLconf searches against the requested URL, as a normal Python string. This does not include GET or POST parameters, or the domain name.
Solution 2:
I just made my own utility function like the one asked in the question:
from django.utils.http import urlencode
def my_reverse(viewname, kwargs=None, query_kwargs=None):
"""
Custom reverse to add a query string after the url
Example usage:
url = my_reverse('my_test_url', kwargs={'pk': object.id}, query_kwargs={'next': reverse('home')})
"""
url = reverse(viewname, kwargs=kwargs)
if query_kwargs:
return f'{url}?{urlencode(query_kwargs)}'
return url
Solution 3:
I think it's better to wrap Django's reverse method to expose this API. Here's some simple code to do it:
from django.core.urlresolvers import reverse as django_reverse
def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None, current_app=None):
"""
Wrapper of django.core.urlresolvers.reverse that attaches arguments in kwargs as query string parameters
"""
if kwargs:
return '%s?%s' % (django_reverse(viewname, urlconf, args, None, prefix, current_app), \
'&'.join(['%s=%s' % (k,v) for k,v in kwargs.items()]))
else:
return django_reverse(viewname, urlconf, args, kwargs, prefix, current_app)
Put this code into some utility or common app that only depends on Django, then instead of importing django.core.urlresolvers.reverse just import myproject.myutils.urlresolvers.reverse