Skip to content

Instantly share code, notes, and snippets.

@zarinpy
Last active October 6, 2019 07:49
Show Gist options
  • Save zarinpy/6db48ac4d342a20d5d127051251ed071 to your computer and use it in GitHub Desktop.
Save zarinpy/6db48ac4d342a20d5d127051251ed071 to your computer and use it in GitHub Desktop.
custom exception ahndler for django rest-framework
from rest_framework.views import exception_handler
from rest_framework.exceptions import ErrorDetail
def custom_exception_handler(exc, context):
if hasattr(exc, 'detail'):
if isinstance(exc.detail, ErrorDetail):
context['kwargs']['message'] = exc.detail.title()
else:
t = exc.get_full_details().popitem()
context['kwargs']['message'] = "input parameters are not valid."
context['kwargs']['exception'] = "{}: {}".format(t[0], t[1][0]['message'].title())
context['kwargs']['code'] = exc.status_code
response = exception_handler(exc, context)
if hasattr(response, 'data'):
response.data = {}
return response
from __future__ import unicode_literals
from django.utils import six
from rest_framework.compat import (
INDENT_SEPARATORS, LONG_SEPARATORS, SHORT_SEPARATORS
)
from rest_framework.renderers import JSONRenderer
from rest_framework.utils import json
def zero_as_none(value):
return None if value == 0 else value
class CustomRenderer(JSONRenderer):
def render(self, data, accepted_media_type=None, renderer_context=None):
if data is None:
return bytes()
renderer_context = renderer_context or {}
indent = self.get_indent(accepted_media_type, renderer_context)
new_data = {
'code': None,
'message': '',
'exception': '',
'data': {},
}
if indent is None:
separators = SHORT_SEPARATORS if self.compact else LONG_SEPARATORS
else:
separators = INDENT_SEPARATORS
if 'code' in renderer_context['kwargs'].keys():
new_data['code'] = renderer_context['kwargs']['code']
else:
new_data['code'] = renderer_context['response'].status_code
if 'message' in renderer_context['kwargs'].keys():
new_data['message'] = renderer_context['kwargs']['message']
if 'exception' in renderer_context['kwargs'].keys():
new_data['exception'] = renderer_context['kwargs']['exception']
new_data['data'] = data
ret = json.dumps(
new_data, cls=self.encoder_class,
indent=indent, ensure_ascii=self.ensure_ascii,
allow_nan=not self.strict, separators=separators
)
if isinstance(ret, six.text_type):
ret = ret.replace('\u2028', '\\u2028').replace('\u2029', '\\u2029')
return bytes(ret.encode('utf-8'))
return ret
@zarinpy
Copy link
Author

zarinpy commented Oct 6, 2019

to design a good api we should consider many things.
imagine we should call a web service in our api and we should response it.
there are some conditions that should be covered in expose.
if our api works correctly but the web service has not and upside down.
this file can handle all the exception type that we should expose.

we can access the kwargs from view by this function self.get_renderer_context() and set kwargs like message, code and exception .

and this custom renderer can handle the expose

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment