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)