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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With