In my project I use DRF as backend and Angular as frontend.
Django==1.10 djangorestframework==3.7.1
I need all responses from DRF to be in the following format.
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 JSONRenderer
class 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)