Loading django/contrib/auth/tests/views.py +7 −6 Original line number Diff line number Diff line Loading @@ -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' Loading @@ -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/' Loading @@ -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' Loading @@ -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/' Loading @@ -298,7 +298,8 @@ 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' Loading django/contrib/auth/views.py +1 −1 Original line number Diff line number Diff line Loading @@ -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)) Loading django/http/__init__.py +22 −3 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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): Loading docs/ref/request-response.txt +20 −6 Original line number Diff line number Diff line Loading @@ -434,10 +434,24 @@ In addition, ``QueryDict`` has the following methods: >>> q.lists() [(u'a', [u'1', u'2', u'3'])] .. method:: QueryDict.urlencode() .. method:: QueryDict.urlencode([safe]) Returns a string of the data in query-string format. Example: ``"a=2&b=3&b=5"``. Returns a string of the data in query-string format. Example:: >>> q = QueryDict('a=2&b=3&b=5') >>> q.urlencode() 'a=2&b=3&b=5' .. versionchanged:: 1.3 The ``safe`` parameter was added. Optionally, urlencode can be passed characters which do not require encoding. For example:: >>> q = QueryDict('', mutable=True) >>> q['next'] = '/a&b/' >>> q.urlencode(safe='/') 'next=/a%26b/' HttpResponse objects ==================== Loading tests/regressiontests/httpwrappers/tests.py +10 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,16 @@ class QueryDictTests(unittest.TestCase): self.assertEqual(q.urlencode(), 'foo=bar') def test_urlencode(self): q = QueryDict('', mutable=True) q['next'] = '/a&b/' self.assertEqual(q.urlencode(), 'next=%2Fa%26b%2F') self.assertEqual(q.urlencode(safe='/'), 'next=/a%26b/') q = QueryDict('', mutable=True) q['next'] = u'/t\xebst&key/' self.assertEqual(q.urlencode(), 'next=%2Ft%C3%ABst%26key%2F') self.assertEqual(q.urlencode(safe='/'), 'next=/t%C3%ABst%26key/') def test_mutable_copy(self): """A copy of a QueryDict is mutable.""" q = QueryDict('').copy() Loading Loading
django/contrib/auth/tests/views.py +7 −6 Original line number Diff line number Diff line Loading @@ -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' Loading @@ -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/' Loading @@ -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' Loading @@ -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/' Loading @@ -298,7 +298,8 @@ 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' Loading
django/contrib/auth/views.py +1 −1 Original line number Diff line number Diff line Loading @@ -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)) Loading
django/http/__init__.py +22 −3 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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): Loading
docs/ref/request-response.txt +20 −6 Original line number Diff line number Diff line Loading @@ -434,10 +434,24 @@ In addition, ``QueryDict`` has the following methods: >>> q.lists() [(u'a', [u'1', u'2', u'3'])] .. method:: QueryDict.urlencode() .. method:: QueryDict.urlencode([safe]) Returns a string of the data in query-string format. Example: ``"a=2&b=3&b=5"``. Returns a string of the data in query-string format. Example:: >>> q = QueryDict('a=2&b=3&b=5') >>> q.urlencode() 'a=2&b=3&b=5' .. versionchanged:: 1.3 The ``safe`` parameter was added. Optionally, urlencode can be passed characters which do not require encoding. For example:: >>> q = QueryDict('', mutable=True) >>> q['next'] = '/a&b/' >>> q.urlencode(safe='/') 'next=/a%26b/' HttpResponse objects ==================== Loading
tests/regressiontests/httpwrappers/tests.py +10 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,16 @@ class QueryDictTests(unittest.TestCase): self.assertEqual(q.urlencode(), 'foo=bar') def test_urlencode(self): q = QueryDict('', mutable=True) q['next'] = '/a&b/' self.assertEqual(q.urlencode(), 'next=%2Fa%26b%2F') self.assertEqual(q.urlencode(safe='/'), 'next=/a%26b/') q = QueryDict('', mutable=True) q['next'] = u'/t\xebst&key/' self.assertEqual(q.urlencode(), 'next=%2Ft%C3%ABst%26key%2F') self.assertEqual(q.urlencode(safe='/'), 'next=/t%C3%ABst%26key/') def test_mutable_copy(self): """A copy of a QueryDict is mutable.""" q = QueryDict('').copy() Loading