Django REST framework custom format for all out responses

后端 未结 2 1350
没有蜡笔的小新
没有蜡笔的小新 2021-02-15 16:00

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.

相关标签:
2条回答
  • 2021-02-15 16:30

    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)
    
    0 讨论(0)
  • 2021-02-15 16:46

    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)
    
    
    0 讨论(0)
提交回复
热议问题