How to obtain a plain text Django error page

后端 未结 5 2123
独厮守ぢ
独厮守ぢ 2020-12-06 02:05

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

相关标签:
5条回答
  • 2020-12-06 02:19

    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
    
    0 讨论(0)
  • 2020-12-06 02:20

    Building off of Timmmm's answer, I had to make several modifications for it to work in Django 3.1:

    Create a file somewhere in your application, such as YOUR_APP_NAME/middleware/exceptions.py and paste the following code:

    import traceback
    from django.http import HttpResponse, HttpRequest
    
    class PlainExceptionsMiddleware:
        def __init__(self, get_response):
            self.get_response = get_response
    
        def __call__(self, request):
            return self.get_response(request)
    
        def process_exception(self, request: HttpRequest, exception: Exception):
            if "HTTP_USER_AGENT" in request.META and "chrome" in request.META["HTTP_USER_AGENT"].lower():
                return
            print(traceback.format_exc())
            return HttpResponse(repr(exception), content_type="text/plain", status=500)
    

    It is not necessary to create an __init__.py file in the middleware folder.

    In settings.py, add the following item to the end of the MIDDLEWARE variable, so that it looks like:

    MIDDLEWARE = [
        # ...
        'YOUR_APP_NAME.middleware.exceptions.PlainExceptionsMiddleware'
    ]
    

    Now, if "HTTP_USER_AGENT" and "chrome" are in the request header, this middleware doesn't do anything, so Django returns an HTML response as usual. Otherwise, it returns a plain-text representation of the error as a response (e.g., ValueError("Field 'id' expected a number but got 'undefined'.")) and prints out the traceback to the Django console, as Django normally would. Of course, you can instead return the full traceback as your response.

    0 讨论(0)
  • 2020-12-06 02:30

    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
    
    0 讨论(0)
  • 2020-12-06 02:31

    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.

    0 讨论(0)
  • 2020-12-06 02:41

    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)
    
    0 讨论(0)
提交回复
热议问题