If I have a error outside the libs of DRF, django send back the HTML of the error instead of the proper error response use by DRF.
For example:
@api_view(['POST'])
@permission_classes((IsAuthenticated,))
def downloadData(request):
print request.POST['tables']
Return the exception MultiValueDictKeyError: "'tables'"
. And get back the full HTML. How get only the error a JSON?
P.D:
This is the final code:
@api_view(['GET', 'POST'])
def process_exception(request, exception):
# response = json.dumps({'status': status.HTTP_500_INTERNAL_SERVER_ERROR,
# 'message': str(exception)})
# return HttpResponse(response,
# content_type='application/json; charset=utf-8')
return Response({
'error': True,
'content': unicode(exception)},
status=status.HTTP_500_INTERNAL_SERVER_ERROR
)
class ExceptionMiddleware(object):
def process_exception(self, request, exception):
# response = json.dumps({'status': status.HTTP_500_INTERNAL_SERVER_ERROR,
# 'message': str(exception)})
# return HttpResponse(response,
# content_type='application/json; charset=utf-8')
print exception
return process_exception(request, exception)
Custom exception handlingThe exception handler function should either return a Response object, or return None if the exception cannot be handled. If the handler returns None then the exception will be re-raised and Django will return a standard HTTP 500 'server error' response.
Django/Python/REST framework is too slow. As this article will argue, the biggest performance gains for Web APIs can be made not by code tweaking, but by proper caching of database lookups, well designed HTTP caching, and running behind a shared server-side cache if possible.
Pagination is only performed automatically if you're using the generic views or viewsets. If you're using a regular APIView , you'll need to call into the pagination API yourself to ensure you return a paginated response. See the source code for the mixins. ListModelMixin and generics.
The browsable API feature in the Django REST framework generates HTML output for different resources. It facilitates interaction with RESTful web service through any web browser. To enable this feature, we should specify text/html for the Content-Type key in the request header.
One way of returning json would be to catch the exceptions and return proper response (assuming you're using JSONParser
as default parser):
from rest_framework.response import Response
from rest_framework import status
@api_view(['POST'])
@permission_classes((IsAuthenticated,))
def downloadData(request):
try:
print request.POST['tables']
except:
return Response({'error': True, 'content': 'Exception!'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
return Response({'error': False})
UPDATE
For global wise use-case the correct idea would be to put the json response in exception middleware.
You can find example in this blog post.
In your case you need to return DRF response, so if any exception gets raised it will end up in the process_exception
:
from rest_framework.response import Response
class ExceptionMiddleware(object):
def process_exception(self, request, exception):
return Response({'error': True, 'content': exception}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
You can replace the default error handlers by specifying a custom handler in your URLConf as documented here
Something like this:
# In urls.py
handler500 = 'my_app.views.api_500'
and:
# In my_app.views
def api_500(request):
response = HttpResponse('{"detail":"An Error Occurred"}', content_type="application/json", status=500)
return response
I hope that helps.
As you can see in the documentation.
All you need to do is configure settings.
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.parsers.JSONParser',
),
'EXCEPTION_HANDLER': 'core.views.api_500_handler',
}
And pointing to a view that will recieve (exception, context)
Like this:
from rest_framework.views import exception_handler
...
def api_500_handler(exception, context):
response = exception_handler(exception, context)
try:
detail = response.data['detail']
except AttributeError:
detail = exception.message
response = HttpResponse(
json.dumps({'detail': detail}),
content_type="application/json", status=500
)
return response
My implementation is like this because if a expected rest framework exception is raised, like a 'exceptions.NotFound', exception.message
will be empty. Thats why Im first calling to exception_handler
of rest framework. If is an expected exception, I will get its message.
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