From f4be8bd53d13c9ecb7f31998f89a2def11111efb Mon Sep 17 00:00:00 2001 From: Jannis Leidel Date: Fri, 22 Apr 2011 12:01:41 +0000 Subject: [PATCH] Fixed #9089 -- Correctly handle list values in MultiValueDict instances when passed to django.utils.http.urlencode. Thanks, kratorius, guettli and obeattie. git-svn-id: http://code.djangoproject.com/svn/django/trunk@16064 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/utils/http.py | 5 ++++- tests/regressiontests/utils/http.py | 30 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/django/utils/http.py b/django/utils/http.py index c93a338c308..4b43e5835ee 100644 --- a/django/utils/http.py +++ b/django/utils/http.py @@ -6,6 +6,7 @@ import urllib import urlparse from email.Utils import formatdate +from django.utils.datastructures import MultiValueDict from django.utils.encoding import smart_str, force_unicode from django.utils.functional import allow_lazy @@ -49,7 +50,9 @@ def urlencode(query, doseq=0): unicode strings. The parameters are first case to UTF-8 encoded strings and then encoded as per normal. """ - if hasattr(query, 'items'): + if isinstance(query, MultiValueDict): + query = query.lists() + elif hasattr(query, 'items'): query = query.items() return urllib.urlencode( [(smart_str(k), diff --git a/tests/regressiontests/utils/http.py b/tests/regressiontests/utils/http.py index 83a4a7f54d7..3f3a36cef7c 100644 --- a/tests/regressiontests/utils/http.py +++ b/tests/regressiontests/utils/http.py @@ -1,5 +1,6 @@ from django.utils import http from django.utils import unittest +from django.utils.datastructures import MultiValueDict class TestUtilsHttp(unittest.TestCase): @@ -21,3 +22,32 @@ class TestUtilsHttp(unittest.TestCase): self.assertFalse(http.same_origin('http://foo.com', 'http://foo.com.evil.com')) # Different port self.assertFalse(http.same_origin('http://foo.com:8000', 'http://foo.com:8001')) + + def test_urlencode(self): + # 2-tuples (the norm) + result = http.urlencode((('a', 1), ('b', 2), ('c', 3))) + self.assertEqual(result, 'a=1&b=2&c=3') + # A dictionary + result = http.urlencode({ 'a': 1, 'b': 2, 'c': 3}) + acceptable_results = [ + # Need to allow all of these as dictionaries have to be treated as + # unordered + 'a=1&b=2&c=3', + 'a=1&c=3&b=2', + 'b=2&a=1&c=3', + 'b=2&c=3&a=1', + 'c=3&a=1&b=2', + 'c=3&b=2&a=1' + ] + self.assertTrue(result in acceptable_results) + # A MultiValueDict + result = http.urlencode(MultiValueDict({ + 'name': ['Adrian', 'Simon'], + 'position': ['Developer'] + }), doseq=True) + acceptable_results = [ + # MultiValueDicts are similarly unordered + 'name=Adrian&name=Simon&position=Developer', + 'position=Developer&name=Adrian&name=Simon' + ] + self.assertTrue(result in acceptable_results)