Django shortcut get_object_or_404 inside Django Rest framework Class Based Views

Viewed 5446

The get_object_or_404 shortcut function in Django when encountering an exception gives a very nice error message in the following format:

'No %s matches the given query.' % queryset.model._meta.object_name)

However, while using this inside a DRF 3.X Class based view, the final 404 response data has a very stripped down version, which is as follows:

{"detail": "Not found."}

As is evident, the DRF message is very generic with no information about the Model name.I am assuming that the DRF NotFound Exception class defined here strips down the message to its current bare minimum.

How can I get the original nice error message that Django returns in-spite of using it within a DRF Class Based View ?

1 Answers

The default exception handler for an APIView class is decided by the get_exception_handler method. Ie,

def get_exception_handler(self):
    """
    Returns the exception handler that this view uses.
    """
    return self.settings.EXCEPTION_HANDLER

In other words the handler function that an APIView class use by default is rest_framework.views.exception_handler(Which is specified on the default settings).

As per the DRF Doc,

By default DRF handle the REST framework APIException, and alsoDjango's built-in Http404 and PermissionDenied exceptions.

Since in this case you want to customize the error message only for the Http404, you can create your own handler like this.

ie,

from rest_framework.views import exception_handler

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 overide the error message.
    if response is not None and isinstance(exc, Http404):
        # set the custom message data on response object
        response.data['detail'] =  exc.args[0] # exc.args[0] will have the message text, 

    return response

Then place this custom handler in your project settings.

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}

Note: This solution is not tested.

Related