Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django shortcut get_object_or_404 inside Django Rest framework Class Based Views

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 ?

like image 580
Amistad Avatar asked Nov 05 '18 06:11

Amistad


People also ask

What is get_object_or_404 in Django?

How to use get_object_or_404() in a Django Project? This function calls the given model and get object from that if that object or model doesn't exist it raise 404 error.

What is Django REST framework views?

Django views facilitate processing the HTTP requests and providing HTTP responses. On receiving an HTTP request, Django creates an HttpRequest instance, and it is passed as the first argument to the view function. This instance contains HTTP verbs such as GET, POST, PUT, PATCH, or DELETE.

What is difference between APIView and Viewset?

APIView allow us to define functions that match standard HTTP methods like GET, POST, PUT, PATCH, etc. Viewsets allow us to define functions that match to common API object actions like : LIST, CREATE, RETRIEVE, UPDATE, etc.

What is QuerySet in Django REST framework?

The root QuerySet provided by the Manager describes all objects in the database table. Usually, though, you'll need to select only a subset of the complete set of objects. The default behavior of REST framework's generic list views is to return the entire queryset for a model manager.


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.

like image 139
Abdul Niyas P M Avatar answered Sep 21 '22 05:09

Abdul Niyas P M