Reputation: 1276
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.
Upvotes: 4
Views: 3858
Reputation: 8028
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
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)
Upvotes: 2
Reputation: 1276
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
Upvotes: 3