diff --git a/django/core/handlers/base.py b/django/core/handlers/base.py
index f144ce4..0ad0482 100644
--- a/django/core/handlers/base.py
+++ b/django/core/handlers/base.py
@@ -1,4 +1,5 @@
 import sys
+from pprint import pformat
 
 from django import http
 from django.core import signals
@@ -170,7 +171,24 @@ class BaseHandler(object):
             request_repr = repr(request)
         except:
             request_repr = "Request repr() unavailable"
-        message = "%s\n\n%s" % (self._get_traceback(exc_info), request_repr)
+        request_metadata = {}
+        for (key, metadata_getter) in (
+            ('GET', lambda request: pformat(request.GET)),
+            ('POST', lambda request: not request._post_parse_error and pformat(request.POST) or '(could not parse)'),
+            ('COOKIES', lambda request: pformat(request.COOKIES)),
+            ('META', lambda request: pformat(request.META))):
+            try:
+                request_metadata[key] = metadata_getter(request)
+            except Exception, e:
+                request_metadata[key] = '(could not parse)'
+        message = "%s\n\nRequest: %s\n\nGET: %s\n\nPOST: %s\n\nCOOKIES: %s\n\nMETA: %s\n\n" % (
+            self._get_traceback(exc_info),
+            request_repr,
+            request_metadata['GET'],
+            request_metadata['POST'],
+            request_metadata['COOKIES'],
+            request_metadata['META'],
+        )
         mail_admins(subject, message, fail_silently=True)
         # Return an HttpResponse that displays a friendly error message.
         callback, param_dict = resolver.resolve500()
diff --git a/django/core/handlers/modpython.py b/django/core/handlers/modpython.py
index b1e3e17..c66fda7 100644
--- a/django/core/handlers/modpython.py
+++ b/django/core/handlers/modpython.py
@@ -1,5 +1,4 @@
 import os
-from pprint import pformat
 
 from django import http
 from django.core import signals
@@ -37,32 +36,6 @@ class ModPythonRequest(http.HttpRequest):
             self.path_info = u'/'
         self._post_parse_error = False
 
-    def __repr__(self):
-        # Since this is called as part of error handling, we need to be very
-        # robust against potentially malformed input.
-        try:
-            get = pformat(self.GET)
-        except:
-            get = '<could not parse>'
-        if self._post_parse_error:
-            post = '<could not parse>'
-        else:
-            try:
-                post = pformat(self.POST)
-            except:
-                post = '<could not parse>'
-        try:
-            cookies = pformat(self.COOKIES)
-        except:
-            cookies = '<could not parse>'
-        try:
-            meta = pformat(self.META)
-        except:
-            meta = '<could not parse>'
-        return smart_str(u'<ModPythonRequest\npath:%s,\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' %
-                         (self.path, unicode(get), unicode(post),
-                          unicode(cookies), unicode(meta)))
-
     def get_full_path(self):
         # RFC 3986 requires self._req.args to be in the ASCII range, but this
         # doesn't always happen, so rather than crash, we defensively encode it.
diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py
index 927b098..646e313 100644
--- a/django/core/handlers/wsgi.py
+++ b/django/core/handlers/wsgi.py
@@ -1,5 +1,4 @@
 from threading import Lock
-from pprint import pformat
 try:
     from cStringIO import StringIO
 except ImportError:
@@ -94,31 +93,6 @@ class WSGIRequest(http.HttpRequest):
         self.method = environ['REQUEST_METHOD'].upper()
         self._post_parse_error = False
 
-    def __repr__(self):
-        # Since this is called as part of error handling, we need to be very
-        # robust against potentially malformed input.
-        try:
-            get = pformat(self.GET)
-        except:
-            get = '<could not parse>'
-        if self._post_parse_error:
-            post = '<could not parse>'
-        else:
-            try:
-                post = pformat(self.POST)
-            except:
-                post = '<could not parse>'
-        try:
-            cookies = pformat(self.COOKIES)
-        except:
-            cookies = '<could not parse>'
-        try:
-            meta = pformat(self.META)
-        except:
-            meta = '<could not parse>'
-        return '<WSGIRequest\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \
-            (get, post, cookies, meta)
-
     def get_full_path(self):
         # RFC 3986 requires query string arguments to be in the ASCII range.
         # Rather than crash if this doesn't happen, we encode defensively.
diff --git a/django/http/__init__.py b/django/http/__init__.py
index 446659b..ce0c86b 100644
--- a/django/http/__init__.py
+++ b/django/http/__init__.py
@@ -1,7 +1,6 @@
 import os
 import re
 from Cookie import BaseCookie, SimpleCookie, CookieError
-from pprint import pformat
 from urllib import urlencode
 from urlparse import urljoin
 try:
@@ -38,9 +37,11 @@ class HttpRequest(object):
         self.method = None
 
     def __repr__(self):
-        return '<HttpRequest\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \
-            (pformat(self.GET), pformat(self.POST), pformat(self.COOKIES),
-            pformat(self.META))
+        try:
+            full_path = self.get_full_path()
+        except:
+            full_path = "(could not parse path)"
+        return smart_str(u'<%s: %s %s>' % (self.__class__.__name__, self.method, full_path))
 
     def get_host(self):
         """Returns the HTTP host using the environment or request headers."""
