I am using django class based view and rest framework
object = self.get_object()
In Detail view if object does not exist and i do get request like
/user/10
then i get this response
{"detail": "not found"}
Now i want to customize that response
like
try:
obj = self.get_object()
except:
raise Exception("This object does not exist")
But thats not working
We can implement a custom exception handler function that returns the custom response in case the object does not exist.
In case a object does not exist, Http404
exception is raised. So, we will check if the exception raised is Http404
and if that is the case, we will return our custom exception message in the response.
from rest_framework.views import exception_handler
from django.http import Http404
def custom_exception_handler(exc, context):
# Call REST framework's default exception handler first,
# to get the standard error response.
response = exception_handler(exc, context)
if isinstance(exc, Http404):
custom_response_data = {
'detail': 'This object does not exist.' # custom exception message
}
response.data = custom_response_data # set the custom response data on response object
return response
After defining our custom exception handler, we need to add this custom exception handler to our DRF settings.
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}
You could create a custom exception class as below, and it would raise APIException with a custom message
and custom status_code
from rest_framework.serializers import ValidationError
from rest_framework import status
class CustomAPIException(ValidationError):
"""
raises API exceptions with custom messages and custom status codes
"""
status_code = status.HTTP_400_BAD_REQUEST
default_code = 'error'
def __init__(self, detail, status_code=None):
self.detail = detail
if status_code is not None:
self.status_code = status_code
and in your views
,
from rest_framework import status
try:
obj = self.get_object()
except:
raise CustomAPIException("This object does not exist", status_code=status.HTTP_404_NOT_FOUND)
The response will be like this
{"detail": "This object does not exist"}
NOTE
the detail
parameter of CustomAPIException
class takes str
,list
and dict
objects. If you provide a dict
object, then it will return that dict as exception response
UPDATE
As @pratibha mentioned, it's not possible to produce desired output if we use this exception class in Serializer's validate()
or validate_xxfieldName()
methods.
Why this behaviour ?
I wrote a similar answer in SO, here Django REST Framework ValidationError always returns 400
How to obtain desired output within the serializer's validate()
method?
Inherit CustomAPIException
from rest_framework.exceptions.APIException
instead of from rest_framework.serializers.ValidationError
ie,
from rest_framework.exceptions import APIException
class CustomAPIException(APIException):
# .... code