From 5bdf1da730368a16beaa077d91457ff625f06bc4 Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Fri, 2 Sep 2005 19:39:47 +0000 Subject: [PATCH] Fixed #394 -- Trailing-slash redirects now retain duplicate name-value query-string pairs, instead of the first of each pair. Added a QueryDict.urlencode() method to accomplish this. Updated the docs. Thanks for the good catch, mlambert git-svn-id: http://code.djangoproject.com/svn/django/trunk@613 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/middleware/common.py | 3 +-- django/utils/httpwrappers.py | 7 +++++++ docs/request_response.txt | 30 +++++++++++++++++++++--------- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/django/middleware/common.py b/django/middleware/common.py index 295855d73e..ee6b68be7e 100644 --- a/django/middleware/common.py +++ b/django/middleware/common.py @@ -4,7 +4,6 @@ from django.utils import httpwrappers from django.core.mail import mail_managers from django.views.core.flatfiles import flat_file import md5, os -from urllib import urlencode class CommonMiddleware: """ @@ -49,7 +48,7 @@ class CommonMiddleware: # Redirect newurl = "%s://%s%s" % (os.environ.get('HTTPS') == 'on' and 'https' or 'http', new_url[0], new_url[1]) if request.GET: - newurl += '?' + urlencode(request.GET) + newurl += '?' + request.GET.urlencode() return httpwrappers.HttpResponseRedirect(newurl) return None diff --git a/django/utils/httpwrappers.py b/django/utils/httpwrappers.py index 4a648d1849..107b63d40b 100644 --- a/django/utils/httpwrappers.py +++ b/django/utils/httpwrappers.py @@ -1,5 +1,6 @@ from Cookie import SimpleCookie from pprint import pformat +from urllib import urlencode import datastructures DEFAULT_MIME_TYPE = 'text/html' @@ -117,6 +118,12 @@ class QueryDict(datastructures.MultiValueDict): self.assert_synchronized() return self._keys + def urlencode(self): + output = [] + for k, list_ in self.data.items(): + output.extend([urlencode({k: v}) for v in list_]) + return '&'.join(output) + def parse_cookie(cookie): if cookie == '': return {} diff --git a/docs/request_response.txt b/docs/request_response.txt index 3f4ccea713..a004b99126 100644 --- a/docs/request_response.txt +++ b/docs/request_response.txt @@ -115,16 +115,20 @@ Methods Example: ``"/music/bands/the_beatles/?print=true"`` -MultiValueDict objects ----------------------- +QueryDict objects +----------------- In an ``HttpRequest`` object, the ``GET`` and ``POST`` attributes are instances -of ``django.utils.datastructures.MultiValueDict``. ``MultiValueDict`` is a -dictionary-like class customized to deal with multiple values for the same key. -This is necessary because some HTML form elements, notably -````, pass +multiple values for the same key. -``MultiValueDict`` implements the following standard dictionary methods: +``QueryDict`` instances are immutable, unless you create a ``copy()`` of them. +That means you can't change attributes of ``request.POST`` and ``request.GET`` +directly. + +``QueryDict`` implements the following standard dictionary methods: * ``__repr__()`` @@ -141,7 +145,11 @@ This is necessary because some HTML form elements, notably * ``has_key(key)`` - * ``items()`` + * ``items()`` -- Just like the standard dictionary ``items()`` method, + except this retains the order for values of duplicate keys, if any. For + example, if the original query string was ``"a=1&b=2&b=3"``, ``items()`` + will return ``[("a", ["1"]), ("b", ["2", "3"])]``, where the order of + ``["2", "3"]`` is guaranteed, but the order of ``a`` vs. ``b`` isn't. * ``keys()`` @@ -150,7 +158,8 @@ This is necessary because some HTML form elements, notably In addition, it has the following methods: * ``copy()`` -- Returns a copy of the object, using ``copy.deepcopy()`` - from the Python standard library. + from the Python standard library. The copy will be mutable -- that is, + you can change its values. * ``getlist(key)`` -- Returns the data with the requested key, as a Python list. Returns an empty list if the key doesn't exist. @@ -161,6 +170,9 @@ In addition, it has the following methods: * ``appendlist(key, item)`` -- Appends an item to the internal list associated with key. + * ``urlencode()`` -- Returns a string of the data in query-string format. + Example: ``"a=2&b=3&b=5"``. + Examples --------