Django REST framework custom format for all out responses
After some research I found a way to do this. I had to override the default behaviour of the ModelViewSet
to output a different response.
I created a custom Response
format initially:
class ResponseInfo(object): def __init__(self, user=None, **args): self.response = { "status": args.get('status', True), "error": args.get('error', 200), "data": args.get('data', []), "message": args.get('message', 'success') }
Then use this custom format in every method of the ModelViewSet
:
class ResponseModelViewSet(viewsets.ModelViewSet): def __init__(self, **kwargs): self.response_format = ResponseInfo().response super(ResponseModelViewSet, self).__init__(**kwargs) def list(self, request, *args, **kwargs): response_data = super(ResponseModelViewSet, self).list(request, *args, **kwargs) self.response_format["data"] = response_data.data self.response_format["status"] = True if not response_data.data: self.response_format["message"] = "List empty" return Response(self.response_format) def create(self, request, *args, **kwargs): response_data = super(ResponseModelViewSet, self).create(request, *args, **kwargs) self.response_format["data"] = response_data.data self.response_format["status"] = True return Response(self.response_format) def retrieve(self, request, *args, **kwargs): response_data = super(ResponseModelViewSet, self).retrieve(request, *args, **kwargs) self.response_format["data"] = response_data.data self.response_format["status"] = True if not response_data.data: self.response_format["message"] = "Empty" return Response(self.response_format) def update(self, request, *args, **kwargs): response_data = super(ResponseModelViewSet, self).update(request, *args, **kwargs) self.response_format["data"] = response_data.data self.response_format["status"] = True return Response(self.response_format) def destroy(self, request, *args, **kwargs): response_data = super(ResponseModelViewSet, self).destroy(request, *args, **kwargs) self.response_format["data"] = response_data.data self.response_format["status"] = True return Response(self.response_format)
This would be more a more robust solution, as it can be used with Generic Views hassle free.
Also, the checks in render() can be easily altered as per the needs (Eg., handling no-2XX in this solution).
from rest_framework.renderers import JSONRendererclass CustomRenderer(JSONRenderer): def render(self, data, accepted_media_type=None, renderer_context=None): status_code = renderer_context['response'].status_code response = { "status": "success", "code": status_code, "data": data, "message": None } if not str(status_code).startswith('2'): response["status"] = "error" response["data"] = None try: response["message"] = data["detail"] except KeyError: response["data"] = data return super(CustomRenderer, self).render(response, accepted_media_type, renderer_context)