Index: django/test/client.py
===================================================================
--- django/test/client.py	(revision 9539)
+++ django/test/client.py	(working copy)
@@ -265,6 +265,7 @@
         r = {
             'CONTENT_TYPE':    'text/html; charset=utf-8',
             'PATH_INFO':       urllib.unquote(parsed[2]),
+            'REQUEST_URI':     parsed[2],
             'QUERY_STRING':    urlencode(data, doseq=True) or parsed[4],
             'REQUEST_METHOD': 'GET',
             'wsgi.input':      FakePayload('')
@@ -287,6 +288,7 @@
             'CONTENT_LENGTH': len(post_data),
             'CONTENT_TYPE':   content_type,
             'PATH_INFO':      urllib.unquote(parsed[2]),
+            'REQUEST_URI':    parsed[2],
             'QUERY_STRING':   parsed[4],
             'REQUEST_METHOD': 'POST',
             'wsgi.input':     FakePayload(post_data),
@@ -303,6 +305,7 @@
         r = {
             'CONTENT_TYPE':    'text/html; charset=utf-8',
             'PATH_INFO':       urllib.unquote(parsed[2]),
+            'REQUEST_URI':     parsed[2],
             'QUERY_STRING':    urlencode(data, doseq=True) or parsed[4],
             'REQUEST_METHOD': 'HEAD',
             'wsgi.input':      FakePayload('')
@@ -318,6 +321,7 @@
         parsed = urlparse(path)
         r = {
             'PATH_INFO':       urllib.unquote(parsed[2]),
+            'REQUEST_URI':     parsed[2],
             'QUERY_STRING':    urlencode(data, doseq=True) or parsed[4],
             'REQUEST_METHOD': 'OPTIONS',
             'wsgi.input':      FakePayload('')
@@ -340,6 +344,7 @@
             'CONTENT_LENGTH': len(post_data),
             'CONTENT_TYPE':   content_type,
             'PATH_INFO':      urllib.unquote(parsed[2]),
+            'REQUEST_URI':    parsed[2],
             'QUERY_STRING':   urlencode(data, doseq=True) or parsed[4],
             'REQUEST_METHOD': 'PUT',
             'wsgi.input':     FakePayload(post_data),
@@ -355,6 +360,7 @@
         parsed = urlparse(path)
         r = {
             'PATH_INFO':       urllib.unquote(parsed[2]),
+            'REQUEST_URI':     parsed[2],
             'QUERY_STRING':    urlencode(data, doseq=True) or parsed[4],
             'REQUEST_METHOD': 'DELETE',
             'wsgi.input':      FakePayload('')
Index: django/core/servers/basehttp.py
===================================================================
--- django/core/servers/basehttp.py	(revision 9539)
+++ django/core/servers/basehttp.py	(working copy)
@@ -566,7 +566,7 @@
         else:
             path,query = self.path,''
 
-        env['PATH_INFO'] = urllib.unquote(path)
+        env['PATH_INFO'] = urllib.unquote_plus(path)
         env['QUERY_STRING'] = query
         env['REMOTE_ADDR'] = self.client_address[0]
 
Index: django/core/handlers/wsgi.py
===================================================================
--- django/core/handlers/wsgi.py	(revision 9539)
+++ django/core/handlers/wsgi.py	(working copy)
@@ -1,5 +1,6 @@
 from threading import Lock
 from pprint import pformat
+import urllib
 try:
     from cStringIO import StringIO
 except ImportError:
@@ -75,7 +76,9 @@
 class WSGIRequest(http.HttpRequest):
     def __init__(self, environ):
         script_name = base.get_script_name(environ)
-        path_info = force_unicode(environ.get('PATH_INFO', u'/'))
+        
+        real_path = environ.get('REQUEST_URI', u'/').split('?')[0]
+        path_info = force_unicode( urllib.unquote_plus(real_path) )
         if not path_info or path_info == script_name:
             # Sometimes PATH_INFO exists, but is empty (e.g. accessing
             # the SCRIPT_NAME URL without a trailing slash). We really need to
Index: django/core/handlers/modpython.py
===================================================================
--- django/core/handlers/modpython.py	(revision 9539)
+++ django/core/handlers/modpython.py	(working copy)
@@ -1,5 +1,6 @@
 import os
 from pprint import pformat
+import urllib
 
 from django import http
 from django.core import signals
@@ -20,14 +21,20 @@
         # and PATH_INFO values. This causes problems when we compute path_info,
         # below. For now, don't use script names that will be subject to
         # encoding/decoding.
-        self.path = force_unicode(req.uri)
+
+        if req.unparsed_uri:
+            req_uri = urllib.unquote_plus(req.unparsed_uri.split('?')[0])
+        else:
+            req_uri = req.uri
+            
+        self.path = force_unicode(req_uri)
         root = req.get_options().get('django.root', '')
         self.django_root = root
         # req.path_info isn't necessarily computed correctly in all
         # circumstances (it's out of mod_python's control a bit), so we use
-        # req.uri and some string manipulations to get the right value.
-        if root and req.uri.startswith(root):
-            self.path_info = force_unicode(req.uri[len(root):])
+        # req_uri and some string manipulations to get the right value.
+        if root and req_uri.startswith(root):
+            self.path_info = force_unicode(req_uri[len(root):])
         else:
             self.path_info = self.path
         if not self.path_info:
Index: tests/regressiontests/file_uploads/tests.py
===================================================================
--- tests/regressiontests/file_uploads/tests.py	(revision 9539)
+++ tests/regressiontests/file_uploads/tests.py	(working copy)
@@ -100,6 +100,7 @@
             'CONTENT_LENGTH': len(payload),
             'CONTENT_TYPE':   client.MULTIPART_CONTENT,
             'PATH_INFO':      "/file_uploads/echo/",
+            'REQUEST_URI':    "/file_uploads/echo/",
             'REQUEST_METHOD': 'POST',
             'wsgi.input':     client.FakePayload(payload),
         }
@@ -127,6 +128,7 @@
             'CONTENT_LENGTH': len(payload),
             'CONTENT_TYPE':   client.MULTIPART_CONTENT,
             'PATH_INFO':      "/file_uploads/echo/",
+            'REQUEST_URI':    "/file_uploads/echo/",
             'REQUEST_METHOD': 'POST',
             'wsgi.input':     client.FakePayload(payload),
         }
Index: tests/regressiontests/requests/tests.py
===================================================================
--- tests/regressiontests/requests/tests.py	(revision 9539)
+++ tests/regressiontests/requests/tests.py	(working copy)
@@ -25,6 +25,7 @@
 ...         return {}
 >>> req = Dummy()
 >>> req.uri = 'bogus'
+>>> req.unparsed_uri = 'bogus'
 >>> print repr(FakeModPythonRequest(req))
 <ModPythonRequest
 path:bogus,
