How does Django's HttpResponse status differ from status_code?
I am trying to set up some custom errors views in a Django application, but I am encountering something I don't quite understand regarding the way HttpResponse works.
When I return
HttpResponse(status=500) Django does not render the
500.html template. However, when I return using status_code
HttpResponse(status_code=500), it works.
Here are the steps to my problem:
- Set up
handler500 = views.handler500
def handler500(request): return render(request, '500.html', status=500)
- Try and replicate a 500 error:
def cart(request): return HttpResponse(status=500)
I am trying to prevent having to refactor hundreds of views in the existing codebase from
status_code=500. I am worried about breaking something. More importantly, I'm trying to understand the difference between the two.
When I read the Django source code for response.py, it seems that they convert
status_code anyway within
class HttpResponseBase. Any and all advice is greatly appreciated.
The argument that HttpResponse wants is
status=<int>. As you note, that gets turned into the property httpresponse.status_code. However, all this is doing making the responseheaders include a 500 error code.
The handler500 is called when an error is raised in a view. It isn't actually triggered by the 500 error code in your responseheaders.
I suspect that using an unexpected keyword argument
status_code = <int> in a view is creating the error necessary for the handler500 to be called. The fact that this is the error you want is confusing the situation. You could verify this by making it
status_code = 404 and seeing if you still get the 500 response.
HttpResponse(status=500) just sends the response with HTTP status code 500, but does not trigger a call to the error handler. Please refer to a related question:
How does HttpResponse(status=<code>) work in django?
If you want to replicate a 500 error, the simplest way is to just raise an unhandled exception in your view, e.g.:
def cart(request): raise Exception()
Why returning HttpResponse(status_code=500) do trigger a call to error handler
__init__() method does not accept the keyword argument
status_code. Trying to create an HttpResponse instance by calling HttpResponse(status_code=500) will raise an exception:
TypeError: init() got an unexpected keyword argument status_code
and if it is not handled, the error handler (custom if it is set or default otherwise) will be called to handle the exception and render your 500.html page.
Please refer to the django documentation: https://docs.djangoproject.com/en/4.1/ref/views/#the-500-server-error-view
Django executes special-case behavior in the case of runtime errors in view code. If a view results in an exception, Django will, by default, call the view django.views.defaults.server_error, which either produces a “Server Error” message or loads and renders the template 500.html if you created it in your root template directory.