Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to obtain a plain text Django error page

During development, I am running Django in Debug mode and I am posting data to my application using a text mode application. Ideally, I need to receive a plain text response when I get an http error code 500 so I don't have to look for the real error inside all that HTML and Javascript.

Is it possible to obtain a Django 500 Internal Server Error as plain text?

like image 980
simao Avatar asked Feb 07 '11 12:02

simao


4 Answers

If you are looking for a way to get a plain text error page when using curl, you need to add the HTTP header X-Requested-With with value XMLHttpRequest, e.g.

curl -H 'X-Requested-With: XMLHttpRequest' http://example.com/some/url/

Explanation: this is because Django uses the is_ajax method to determine whether or not to return as plain text or as HTML. is_ajax in turn looks at X-Requested-With.


Update

Since django version 3.1, error reporting ignores the X-Requested-With header. Instead, set the Accept header on the request to any valid value which does not include the text/html mime type.

e.g.

curl -H 'Accept: application/json;charset=utf-8' http://example.comp/some/url
like image 115
Martijn de Milliano Avatar answered Nov 05 '22 12:11

Martijn de Milliano


This is an improvement on Yuji's answer, which provides a stacktrace, more instructions (for us django newbies) and is simpler.

Put this code in a file somewhere in your application, e.g. PROJECT_ROOT/MAIN_APP/middleware/exceptions.py, and make sure you have an empty __init__.py in the same directory.

import traceback
from django.http import HttpResponse

class PlainExceptionsMiddleware(object):
    def process_exception(self, request, exception):
        return HttpResponse(traceback.format_exc(exception), content_type="text/plain", status=500)

Now edit your settings.py and find MIDDLEWARE_CLASSES = (. Add another entry so it is like this:

MIDDLEWARE_CLASSES = (
    # (all the previous entries)

    # Plain text exception pages.
    'MAIN_APP.middleware.exceptions.PlainExceptionsMiddleware',
)

Restart django and you are good to go!

User-agent aware formatting.

If you're like me and developing an app and a website both backed by django, you probably want to show plain text error pages to the app, and the nice formatted ones to the browser. A simple way to to that is to check the user agent:

import traceback
from django.http import HttpResponse

class PlainExceptionsMiddleware(object):
    def process_exception(self, request, exception):
        if "HTTP_USER_AGENT" in request.META and "chrome" in request.META["HTTP_USER_AGENT"].lower():
            return
        return HttpResponse(traceback.format_exc(exception), content_type="text/plain", status=500)
like image 30
Timmmm Avatar answered Sep 18 '22 05:09

Timmmm


I think to write a middleware, because otherwise the exception isn't available in the 500.html

http://docs.djangoproject.com/en/dev/topics/http/middleware/#process-exception

class ProcessExceptionMiddleware(object):
    def process_exception(self, request, exception):
        t = Template("500 Error: {{ exception }}")
        response_html = t.render(Context({'exception' : exception }))

        response = http.HttpResponse(response_html)
        response.status_code = 500
        return response
like image 8
Yuji 'Tomita' Tomita Avatar answered Nov 05 '22 13:11

Yuji 'Tomita' Tomita


There's a setting DEBUG_PROPAGATE_EXCEPTIONS which will force Django not to wrap the exceptions, so you can see them, e.g. in devserver logs.

like image 8
Dmitry Shevchenko Avatar answered Nov 05 '22 13:11

Dmitry Shevchenko