Skip to content

Commit

Permalink
Fixed #14809 -- broken login related tests after r14733.
Browse files Browse the repository at this point in the history
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14764 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
SmileyChris committed Dec 1, 2010
1 parent cd847db commit dceaa82
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 16 deletions.
13 changes: 7 additions & 6 deletions django/contrib/auth/tests/views.py
Expand Up @@ -265,31 +265,31 @@ def test_standard_login_url(self):
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'
login_required_url = self.get_login_required_url(login_url)
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/'
login_required_url = self.get_login_required_url(login_url)
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'
login_required_url = self.get_login_required_url(login_url)
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/'
Expand All @@ -298,8 +298,9 @@ def test_remote_login_url_with_next_querystring(self):
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'

Expand Down
2 changes: 1 addition & 1 deletion django/contrib/auth/views.py
Expand Up @@ -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))

Expand Down
25 changes: 22 additions & 3 deletions django/http/__init__.py
Expand Up @@ -3,7 +3,7 @@
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
Expand Down Expand Up @@ -363,11 +363,30 @@ def copy(self):
"""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):
Expand Down
26 changes: 20 additions & 6 deletions docs/ref/request-response.txt
Expand Up @@ -430,14 +430,28 @@ In addition, ``QueryDict`` has the following methods:
Like :meth:`items()`, except it includes all values, as a list, for each
member of the dictionary. For example::

>>> q = QueryDict('a=1&a=2&a=3')
>>> q.lists()
[(u'a', [u'1', u'2', u'3'])]
>>> q = QueryDict('a=1&a=2&a=3')
>>> 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
====================
Expand Down
10 changes: 10 additions & 0 deletions tests/regressiontests/httpwrappers/tests.py
Expand Up @@ -71,6 +71,16 @@ def test_single_key_value(self):

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()
Expand Down

0 comments on commit dceaa82

Please sign in to comment.