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:

  1. Set up handler500 = views.handler500
  2. Build handler500 view:
def handler500(request):
    return render(request, '500.html', status=500)
  1. 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=500 to 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 to 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.

Returning HttpResponse(status=500)

Returning 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

HttpResponse __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.

Back to Top