diff options
Diffstat (limited to 'django')
| -rw-r--r-- | django/contrib/auth/tests/views.py | 13 | ||||
| -rw-r--r-- | django/contrib/auth/views.py | 2 | ||||
| -rw-r--r-- | django/http/__init__.py | 25 |
3 files changed, 30 insertions, 10 deletions
diff --git a/django/contrib/auth/tests/views.py b/django/contrib/auth/tests/views.py index 88867d538c..014c8195fc 100644 --- a/django/contrib/auth/tests/views.py +++ b/django/contrib/auth/tests/views.py @@ -265,7 +265,7 @@ class LoginURLSettings(AuthViewsTestCase): querystring = QueryDict('', mutable=True) querystring['next'] = '/login_required/' self.assertEqual(login_required_url, - 'http://testserver%s?%s' % (login_url, querystring.urlencode())) + 'http://testserver%s?%s' % (login_url, querystring.urlencode('/'))) def test_remote_login_url(self): login_url = 'http://remote.example.com/login' @@ -273,7 +273,7 @@ class LoginURLSettings(AuthViewsTestCase): querystring = QueryDict('', mutable=True) querystring['next'] = 'http://testserver/login_required/' self.assertEqual(login_required_url, - '%s?%s' % (login_url, querystring.urlencode())) + '%s?%s' % (login_url, querystring.urlencode('/'))) def test_https_login_url(self): login_url = 'https:///login/' @@ -281,7 +281,7 @@ class LoginURLSettings(AuthViewsTestCase): querystring = QueryDict('', mutable=True) querystring['next'] = 'http://testserver/login_required/' self.assertEqual(login_required_url, - '%s?%s' % (login_url, querystring.urlencode())) + '%s?%s' % (login_url, querystring.urlencode('/'))) def test_login_url_with_querystring(self): login_url = '/login/?pretty=1' @@ -289,7 +289,7 @@ class LoginURLSettings(AuthViewsTestCase): querystring = QueryDict('pretty=1', mutable=True) querystring['next'] = '/login_required/' self.assertEqual(login_required_url, 'http://testserver/login/?%s' % - querystring.urlencode()) + querystring.urlencode('/')) def test_remote_login_url_with_next_querystring(self): login_url = 'http://remote.example.com/login/' @@ -298,8 +298,9 @@ class LoginURLSettings(AuthViewsTestCase): querystring = QueryDict('', mutable=True) querystring['next'] = 'http://testserver/login_required/' self.assertEqual(login_required_url, '%s?%s' % (login_url, - querystring.urlencode())) - + querystring.urlencode('/'))) + + class LogoutTest(AuthViewsTestCase): urls = 'django.contrib.auth.tests.urls' diff --git a/django/contrib/auth/views.py b/django/contrib/auth/views.py index 42ad68d3c3..0325643c11 100644 --- a/django/contrib/auth/views.py +++ b/django/contrib/auth/views.py @@ -99,7 +99,7 @@ def redirect_to_login(next, login_url=None, if redirect_field_name: querystring = QueryDict(login_url_parts[4], mutable=True) querystring[redirect_field_name] = next - login_url_parts[4] = querystring.urlencode() + login_url_parts[4] = querystring.urlencode(safe='/') return HttpResponseRedirect(urlparse.urlunparse(login_url_parts)) diff --git a/django/http/__init__.py b/django/http/__init__.py index 42027f0beb..90c55c6319 100644 --- a/django/http/__init__.py +++ b/django/http/__init__.py @@ -3,7 +3,7 @@ import os import re import time from pprint import pformat -from urllib import urlencode +from urllib import urlencode, quote from urlparse import urljoin try: from cStringIO import StringIO @@ -363,11 +363,30 @@ class QueryDict(MultiValueDict): """Returns a mutable copy of this object.""" return self.__deepcopy__({}) - def urlencode(self): + def urlencode(self, safe=None): + """ + Returns an encoded string of all query string arguments. + + :arg safe: Used to specify characters which do not require quoting, for + example:: + + >>> q = QueryDict('', mutable=True) + >>> q['next'] = '/a&b/' + >>> q.urlencode() + 'next=%2Fa%26b%2F' + >>> q.urlencode(safe='/') + 'next=/a%26b/' + + """ output = [] + if safe: + encode = lambda k, v: '%s=%s' % ((quote(k, safe), quote(v, safe))) + else: + encode = lambda k, v: urlencode({k: v}) for k, list_ in self.lists(): k = smart_str(k, self.encoding) - output.extend([urlencode({k: smart_str(v, self.encoding)}) for v in list_]) + output.extend([encode(k, smart_str(v, self.encoding)) + for v in list_]) return '&'.join(output) class CompatCookie(SimpleCookie): |
