3

I have a generic class based view:

class ProjectDetails(mixins.RetrieveModelMixin,
                     mixins.UpdateModelMixin,
                     generics.GenericAPIView):
    queryset = Project.objects.all()
    # Rest of definition

And in my urls.py, I have:

urlpatterns = [
    url(r'^(?P<pk>[0-9]+)/$', views.ProjectDetails.as_view())
]

When the API is called with a non-existent id, it returns HTTP 404 response with the content:

{
    "detail": "Not found."
}

Is it possible to modify this response?

I need to customize error message for this view only.

2 Answers 2

10

This solution affect all views:

Surely you can supply your custom exception handler: Custom exception handling

from rest_framework.views import exception_handler
from rest_framework import status

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)

    # Now add the HTTP status code to the response.
    if response.status_code == status.HTTP_404_NOT_FOUND:
        response.data['custom_field'] = 'some_custom_value'

    return response

Sure you can skip default rest_framework.views.exception_handler and make it completely raw.

Note: remember to mention your handler in django.conf.settings.REST_FRAMEWORK['EXCEPTION_HANDLER']

Solution for specific view:

from rest_framework.response import Response
# rest of the imports

class ProjectDetails(mixins.RetrieveModelMixin,
                     mixins.UpdateModelMixin,
                     generics.GenericAPIView):
    queryset = Project.objects.all()

    def handle_exception(self, exc):
        if isinstance(exc, Http404):
            return Response({'data': 'your custom response'}, 
                            status=status.HTTP_404_NOT_FOUND)

        return super(ProjectDetails, self).handle_exception(exc)
Sign up to request clarification or add additional context in comments.

3 Comments

If I add this, the response will be the same for all views, right? I need it for a single view.
@Arun for all view, yeah. I haven't noticed that you need it to be for specific view.
@Arun i've updated my question with your specific case.
3

It's possible by overriding specific methods like update, retrieve as:

from django.http import Http404
from rest_framework.response import Response


class ProjectDetails(mixins.RetrieveModelMixin,
                     mixins.UpdateModelMixin,
                     generics.GenericAPIView):
    queryset = Project.objects.all()

    def retrieve(self, request, *args, **kwargs):
        try:
            return super().retrieve(request, *args, **kwargs)
        except Http404:
            return Response(data={"cusom": "message"})

    def update(self, request, *args, **kwargs):
        try:
            return super().update(request, *args, **kwargs)
        except Http404:
            return Response(data={"cusom": "message"})

2 Comments

This answer doesn't handle PUT and PATCH methods.:)
@vishes_shell Yeah, but now it does :)

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.