diff --git a/django/http/__init__.py b/django/http/__init__.py index 0124022478..bbbd1ba99a 100644 --- a/django/http/__init__.py +++ b/django/http/__init__.py @@ -128,6 +128,11 @@ class QueryDict(MultiValueDict): Values retrieved from this class are converted from the given encoding (DEFAULT_CHARSET by default) to unicode. """ + # These are both reset in __init__, but is specified here at the class + # level so that unpickling will have valid values + _mutable = True + _encoding = None + def __init__(self, query_string, mutable=False, encoding=None): MultiValueDict.__init__(self) if not encoding: @@ -136,12 +141,24 @@ class QueryDict(MultiValueDict): from django.conf import settings encoding = settings.DEFAULT_CHARSET self.encoding = encoding - self._mutable = True for key, value in parse_qsl((query_string or ''), True): # keep_blank_values=True self.appendlist(force_unicode(key, encoding, errors='replace'), force_unicode(value, encoding, errors='replace')) self._mutable = mutable + def _get_encoding(self): + if self._encoding is None: + # *Important*: do not import settings at the module level because + # of the note in core.handlers.modpython. + from django.conf import settings + self._encoding = settings.DEFAULT_CHARSET + return self._encoding + + def _set_encoding(self, value): + self._encoding = value + + encoding = property(_get_encoding, _set_encoding) + def _assert_mutable(self): if not self._mutable: raise AttributeError("This QueryDict instance is immutable") diff --git a/tests/regressiontests/httpwrappers/tests.py b/tests/regressiontests/httpwrappers/tests.py index 31b956a99d..5e42ff3b63 100644 --- a/tests/regressiontests/httpwrappers/tests.py +++ b/tests/regressiontests/httpwrappers/tests.py @@ -392,17 +392,26 @@ u'\ufffd' [u'bar', u'\ufffd'] -###################################### -# HttpResponse with Unicode headers # -###################################### - ->>> r = HttpResponse() - +######################## +# Pickling a QueryDict # +######################## +>>> import pickle +>>> q = QueryDict('a=b&c=d') +>>> q1 = pickle.loads(pickle.dumps(q)) +>>> q == q1 +True + +###################################### +# HttpResponse with Unicode headers # +###################################### + +>>> r = HttpResponse() + If we insert a unicode value it will be converted to an ascii string. This makes sure we comply with the HTTP specifications. - ->>> r['value'] = u'test value' ->>> isinstance(r['value'], str) + +>>> r['value'] = u'test value' +>>> isinstance(r['value'], str) True An error is raised When a unicode object with non-ascii is assigned. @@ -411,10 +420,10 @@ An error is raised When a unicode object with non-ascii is assigned. Traceback (most recent call last): ... UnicodeEncodeError: ..., HTTP response headers must be in US-ASCII format - -The response also converts unicode keys to strings. - ->>> r[u'test'] = 'testing key' + +The response also converts unicode keys to strings. + +>>> r[u'test'] = 'testing key' >>> l = list(r.items()) >>> l.sort() >>> l[1] @@ -426,7 +435,7 @@ It will also raise errors for keys with non-ascii data. Traceback (most recent call last): ... UnicodeEncodeError: ..., HTTP response headers must be in US-ASCII format - + """ from django.http import QueryDict, HttpResponse