4

How to customize Django rest framework error page. Can't find about it. In my rest action code:

from django.http import Http404

class SomeAction(APIView):
    def get(self, *args, **kwargs):
        raise Http404()

I need to display custom error page in prod.

3
  • 1
    Just place a 404.html file in your template folder. Commented Feb 6, 2015 at 13:48
  • with my rest_framework its not working. I had to add custom error handler to serve error pages. Don't know it's a good solution but works Commented Feb 6, 2015 at 15:09
  • How did you do that? You should supply that as an answer! Commented Feb 6, 2015 at 15:12

2 Answers 2

3
from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.template import loader, RequestContext, Context
from apps.settings import DEBUG
from libs.requestprovider.middleware import get_current_request

from rest_framework.views import exception_handler



def custom_exception_handler(exc):
    # Call REST framework's default exception handler first,
    # to get the standard error response.
    response = exception_handler(exc)

    # Now add the HTTP status code to the response.
    if response is not None:
        response.data['status_code'] = response.status_code

    if not DEBUG:
        #errors can be more generic
        if response.data['status_code'] == 404:
            t = loader.get_template('404.html')
            c = RequestContext(get_current_request(), {})
            return HttpResponse(t.render(c), content_type="text/html")
    return response
Sign up to request clarification or add additional context in comments.

4 Comments

This code seems helpful - but where should I put it?!
@Tadhg wherever you want, I created it in rest/exception_handlers. Most important is config, for example: REST_FRAMEWORK = { 'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler' }
Hmm... my exception handler is being ignored. I'm running Django REST 3.3.x, do you know if this is a feature of a later version?
This might be useful for others who stumble across this issue: django-rest-framework.org/api-guide/exceptions "Note that the exception handler will only be called for responses generated by raised exceptions. It will not be used for any responses returned directly by the view, such as the HTTP_400_BAD_REQUEST responses that are returned by the generic views when serializer validation fails."
2

TL;DR

class YourAPIView(APIView):
    @staticmethod
    def my_exception_handler(exc, context):
        response = exception_handler(exc, context)
        if if response.status_code >= 400:
            return HttpResponse(loader.get_template('your.html').render(context), content_type='text/html')
        return response

    def get_exception_handler(self):
        return self.my_exception_handler

Long story

This link (custom-exception-handling) tells you to set EXCEPTION_HANDLER to yours, and you will notice that the default settings is rest_framework.views.exception_handler

Of course, you can follow the tutorial, but if you don't want to use global settings to control, then see the following.

I suggest you set breakpoints on the function (rest_framework.views.exception_handler) to see what is going on, and then you will know all proceeding.

If you don't want to debug, I list the key points below.

# rest_framework\views.py

class APIView(View):
    ...

    def dispatch(self, request, *args, **kwargs):
        ...
        try:
            ...
        except Exception as exc:
            response = self.handle_exception(exc)  # <-- focus here
        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response
    
     def handle_exception(self, exc):
        ...
        exception_handler = self.get_exception_handler()  # <-- focus here
    
        context = self.get_exception_handler_context()
        response = exception_handler(exc, context)
        ...
        return response
    
    def get_exception_handler(self):
        return self.settings.EXCEPTION_HANDLER

From the above code, you know you can change get_exception_handler then all down!

here is an example:

# views.py

from rest_framework import generics
from django.http import HttpResponse
from rest_framework import status
from django.template import loader
from rest_framework.views import exception_handler


class YourAPIView(generics.ListAPIView):
    ...
    def get(self, request, *args, **kwargs):
        return HttpResponse('ok', content_type='text/html')

    @staticmethod
    def my_exception_handler(exc, context):
        response = exception_handler(exc, context)  # <-- this is the default exception_handler
        if response.status_code in (status.HTTP_400_BAD_REQUEST, status.HTTP_401_UNAUTHORIZED, status.HTTP_403_FORBIDDEN):
            my_400_and_403_template = loader.get_template('error.html')  #  settings.py -> TEMPLATES = [{'DIRS': [ str(Path(BASE_DIR)/Path('templates/your_custom_dir')).replace('\\', '/') ]}]  # Where your_custom_dir should contain error.html
            return HttpResponse(my_400_and_403_template.render(context), content_type='text/html')
        return response

    def get_exception_handler(self):
        return self.my_exception_handler

    # def handle_exception(self, exc):
    #    return super().handle_exception(exc)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.