4

Tech used:

http://www.django-rest-framework.org

Exceptions: http://www.django-rest-framework.org/api-guide/exceptions/

Included rest_framework default example in custom exceptions.py file:

from rest_framework.views import exception_handler

import sys

def custom_exception_handler(exc, context=None):

    # 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 and rename detail to error
    if response is not None:
        response.data['status_code'] = response.status_code
        response.data['request'] = request
        response.data['error'] = response.data.get('detail')
        del response.data['detail']

    return response

This sends basic error info like "Http404" etc, but no request data, like ip address, etc.

Best way to add my request into the response? Thanks in advance.

UPDATE (and solved):

So, I was initially trying to solve this using DjangoRestFramework 2.4.x, but that version doesn't have the request or context data options for the custom exception handler. Upgrading to 3.1.3 made it easy to add the data into the response. New code now looks like this (using version 3.1.3):

def custom_exception_handler(exc, request):

# Call REST framework's default exception handler first,
# to get the standard error response.
response = exception_handler(exc, request)

# Send error to rollbar
rollbar.report_exc_info(sys.exc_info(), request)

# Now add the HTTP status code to the response and rename detail to error
if response is not None:
    response.data['status_code'] = response.status_code
    response.data['error'] = response.data.get('detail')
    del response.data['detail']

return response
2
  • Please check the indentation of response = exception_handler(exc). Is it correct? Commented Jun 11, 2015 at 16:15
  • 1
    Thanks Rahul - yeah its correct - just looks wrong with how I pasted it here Commented Jun 11, 2015 at 16:32

1 Answer 1

5

This should work for your case.

from rest_framework.views import exception_handler

import sys

def custom_exception_handler(exc, context=None):

    # 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 and rename detail to error
    if response is not None:
        response.data['status_code'] = response.status_code
        response.data['request'] = context['request']
        response.data['error'] = response.data.get('detail')
        del response.data['detail']

    return response

You can access the request from the context passed to the custom_exception_handler. This was added in DRF 3.1.0. Also refer this issue where it was resolved.

If you are using DRF<3.1, there would be no request in the context of exception handler. You can upgrade to DRF 3.1.3(latest version in PyPI) and then easily access the request in context.

Taken from DRF 3.1.1 source code:

def get_exception_handler_context(self):
    """
    Returns a dict that is passed through to EXCEPTION_HANDLER,
    as the `context` argument.
    """
    return {
        'view': self,
        'args': getattr(self, 'args', ()),
        'kwargs': getattr(self, 'kwargs', {}),
        'request': getattr(self, 'request', None)
    }

Also, you need to configure the exception handler in your settings.py file.

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

If it is not specified, the 'EXCEPTION_HANDLER' setting defaults to the standard exception handler provided by REST framework:

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'
}

Note:

Exception handler will only be called for responses generated by raised exceptions. It will not be used for any responses returned directly by the view, such as the HTTP_400_BAD_REQUEST responses that are returned by the generic views when serializer validation fails.

Sign up to request clarification or add additional context in comments.

10 Comments

Thanks Rahul - I actually have that already, but the request needs to be defined...
Hi Rahul - yup I've added the exception handler to my settings.py file already too - but still can't get that info... thanks agian for your help
Try accessing request by context['request'] if that works.
I'm getting 'NoneType' object is not subscriptable
Try putting a debugger like ipdb in custom_handler_exception in your code and see what you are getting in context.
|

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.