Index: django/http/__init__.py
===================================================================
--- django/http/__init__.py	(revision 7534)
+++ django/http/__init__.py	(working copy)
@@ -158,6 +158,32 @@
                             force_unicode(value, encoding, errors='replace'))
         self._mutable = mutable
 
+
+    def __new__(cls, query_string, mutable=False, encoding=None):
+        """Premise: when an instance of a QueryDict is being unpickled, 
+        __init__() is never called by the unpickler (as documented at 
+        http://docs.python.org/lib/pickle-inst.html). As a result, the 
+        unpickled instance does not have the attributes _mutable and encoding. 
+        That makes __setitem__ calls fail during the unpickle.
+        
+        Solution: The following override ensures that the instance being 
+        unpickled will always have the attributes _mutable and encoding.
+        
+        This method together with __getnewargs__() ensure that 
+        **mutable copies** of the QueryDict can be pickled and unpickled.
+        """
+        obj = super(QueryDict, cls).__new__(cls, query_string, mutable=mutable, encoding=encoding)
+        obj._mutable = mutable
+        obj.encoding = encoding
+        return obj
+
+    def __getnewargs__(self):
+        """This method is called when an instance of this class is being pickled.
+        The returned tuple is saved by the pickler and it is then passed back to
+        QueryDict.__new__() when the object is being unpickled.
+        """ 
+        return ("", self._mutable, self.encoding)
+
     def _assert_mutable(self):
         if not self._mutable:
             raise AttributeError("This QueryDict instance is immutable")
@@ -239,6 +265,7 @@
             output.extend([urlencode({k: smart_str(v, self.encoding)}) for v in list_])
         return '&'.join(output)
 
+
 def parse_cookie(cookie):
     if cookie == '':
         return {}
