Index: django/views/debug.py
===================================================================
--- django/views/debug.py	(revision 10838)
+++ django/views/debug.py	(working copy)
@@ -37,6 +37,9 @@
     the values returned from sys.exc_info() and friends.
     """
     reporter = ExceptionReporter(request, exc_type, exc_value, tb)
+    if not request.is_ajax():
+        text = reporter.get_traceback_text()
+        return HttpResponseServerError(text, mimetype='text/plain')
     html = reporter.get_traceback_html()
     return HttpResponseServerError(html, mimetype='text/html')
 
@@ -59,9 +62,7 @@
             self.exc_value = Exception('Deprecated String Exception: %r' % self.exc_type)
             self.exc_type = type(self.exc_value)
 
-    def get_traceback_html(self):
-        "Return HTML code for traceback."
-
+    def get_traceback_data(self):
         if issubclass(self.exc_type, TemplateDoesNotExist):
             from django.template.loader import template_source_loaders
             self.template_does_not_exist = True
@@ -93,8 +94,7 @@
                 unicode_str = self.exc_value.args[1]
                 unicode_hint = smart_unicode(unicode_str[max(start-5, 0):min(end+5, len(unicode_str))], 'ascii', errors='replace')
         from django import get_version
-        t = Template(TECHNICAL_500_TEMPLATE, name='Technical 500 template')
-        c = Context({
+        return {
             'exception_type': self.exc_type.__name__,
             'exception_value': smart_unicode(self.exc_value, errors='replace'),
             'unicode_hint': unicode_hint,
@@ -110,9 +110,21 @@
             'template_info': self.template_info,
             'template_does_not_exist': self.template_does_not_exist,
             'loader_debug_info': self.loader_debug_info,
-        })
+        }
+
+    def get_traceback_html(self):
+        "Return HTML code version of traceback."
+        t = Template(TECHNICAL_500_TEMPLATE, name='Technical 500 template')
+        c = Context(self.get_traceback_data())
         return t.render(c)
 
+    def get_traceback_text(self):
+        "Return plain text version of traceback."
+        t = Template(TECHNICAL_500_TEXT_TEMPLATE,
+                     name='Technical 500 template')
+        c = Context(self.get_traceback_data(), autoescape=False)
+        return t.render(c)
+
     def get_template_exception_info(self):
         origin, (start, end) = self.exc_value.source
         template_source = origin.reload()
@@ -276,6 +288,69 @@
 # always work even if the template loader is broken.
 #
 
+TECHNICAL_500_TEXT_TEMPLATE = """{{ exception_type }} at {{ request.path_info }}
+{{ exception_value }}
+
+Request Method: {{ request.META.REQUEST_METHOD }}
+Request URL: {{ request_protocol }}://{{ request.META.HTTP_HOST }}{{ request.path_info }}
+
+Server time: {{server_time|date:"r"}}
+Django Version: {{ django_version_info }}
+Python Version: {{ sys_version_info }}
+Python Path: {{ sys_path }}
+Python Executable: {{ sys_executable }}
+Installed Applications:
+{{ settings.INSTALLED_APPS|pprint }}
+Installed Middleware:
+{{ settings.MIDDLEWARE_CLASSES|pprint }}
+
+{% if template_does_not_exist %}Template Loader Error:
+{% if loader_debug_info %}Django tried loading these templates, in this order:
+{% for loader in loader_debug_info %}Using loader {{ loader.loader }}:
+{% for t in loader.templates %}{{ t.name }} (File {% if t.exists %}exists{% else %}does not exist{% endif %})
+{% endfor %}{% endfor %}
+{% else %}Django couldn't find any templates because your TEMPLATE_LOADERS setting is empty!
+{% endif %}
+{% endif %}{% if template_info %}
+Template error:
+In template {{ template_info.name }}, error at line {{ template_info.line }}
+   {{ template_info.message }}{% for source_line in template_info.source_lines %}{% ifequal source_line.0 template_info.line %}
+   {{ source_line.0 }} : {{ template_info.before }} {{ template_info.during }} {{ template_info.after }}
+{% else %}
+   {{ source_line.0 }} : {{ source_line.1 }}
+{% endifequal %}{% endfor %}{% endif %}
+Traceback:
+{% for frame in frames %}File "{{ frame.filename }}" in {{ frame.function }}
+{% if frame.context_line %}  {{ frame.lineno }}. {{ frame.context_line }}{% endif %}
+{% endfor %}
+Exception Type: {{ exception_type }} at {{ request.path_info }}
+Exception Value: {{ exception_value }}
+
+Request information:
+GET:{% for k, v in request.GET.items %}
+{{ k }} = {{ v|stringformat:"r" }}{% empty %} No GET data{% endfor %}
+
+POST:{% for k, v in request.POST.items %}
+{{ k }} = {{ v|stringformat:"r" }}{% empty %} No POST data{% endfor %}
+
+FILES:{% for k, v in request.FILES.items %}
+{{ k }} = {{ v|stringformat:"r" }}{% empty %} No FILES data{% endfor %}
+
+COOKIES:{% for k, v in request.COOKIES.items %}
+{{ k }} = {{ v|stringformat:"r" }}{% empty %} No cookie data{% endfor %}
+
+META:{% for k, v in request.META.items|dictsort:"0" %}
+{{ k }} = {{ v|stringformat:"r" }}{% endfor %}
+
+Settings:
+Using settings module {{ settings.SETTINGS_MODULE }}{% for k, v in settings.items|dictsort:"0" %}
+{{ k }} = {{ v|stringformat:"r" }}{% endfor %}
+
+    You're seeing this error because you have DEBUG = True in your
+    Django settings file. Change that to False, and Django will
+    display a standard 500 page.
+"""
+
 TECHNICAL_500_TEMPLATE = """
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 <html lang="en">
@@ -630,8 +705,8 @@
   {% else %}
     <p>No FILES data</p>
   {% endif %}
-  
 
+
   <h3 id="cookie-info">COOKIES</h3>
   {% if request.COOKIES %}
     <table class="req">
