Django REST 框架自定义格式,用于所有输出响应



在我的项目中,我使用DRF作为后端,使用Angular作为前端。

姜戈==1.10Djangorestframework==3.7.1

我需要 DRF 的所有回复采用以下格式。

{
 "status": "",  //  200,400,.....etc
 "error": "",   //  True, False
 "data": [],    //  data
 "message": ""  //  Success messages
}

目前它在

[
    {
        "id": 1,
        "name": ""
    },
    {
        "id": 2,
        "name": ""
    }
]

它应该是

{
     "status": "200",   
     "error": "False",      
     "data": [
               {
                   "id": 1,
                   "name": ""
                },
                {
                   "id": 2,
                   "name": ""
                }
            ],    
     "message": "Success"  
}

为此,我编写了一个自定义视图集并覆盖了函数列表、详细信息、创建、更新

class ResponseModelViewSet(viewsets.ModelViewSet):
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = self.get_serializer(queryset, many=True)
        custom_data = {
            "status": True,
            "error": False,
            "message": 'message',
            "data": serializer.data
        }
        return Response(custom_data)
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        custom_data = {
            "status": True,
            "error": False,
            "message": 'message',
            "data": serializer.data
        }
        return Response(custom_data, status=status.HTTP_201_CREATED, headers=headers)
    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        custom_data = {
            "status": True,
            "error": False,
            "message": 'message',
            "data": serializer.data
        }
        return Response(custom_data)
    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}
        custom_data = {
            "status": True,
            "error": False,
            "message": 'message',
            "data": serializer.data
        }
        return Response(custom_data)

在视图中,我使用我的自定义视图集

from common.baseview import ResponseModelViewSet
class PositionViewsets(ResponseModelViewSet):
    serializer_class = PositionSerializer
    permission_classes = (IsAuthenticated,)
    model = Position
    def get_queryset(self):
        return Position.objects.filter(order__user=self.request.user)

我不确定这是否是正确的方法,或者还有其他一些有效的方法可以做到这一点。无论如何,这适用于我的自定义应用程序,但不适用于身份验证应用程序我使用了默认的 REST 应用程序

'rest_framework.authtoken',
'rest_auth',

使用用户名和密码登录,并获得成功响应,如下所示。

{
    "key": "e642efd0b78e08b57bf34fa999f49b70a7bfe21a"
}

相反,我需要这个。

{
 "status": "200",   
 "error": "False",      
 "data": [
          {
           "token":{ 
                     "key":"e642efd0b78e08b57bf34fa999f49b70a7bfe21a"
                    }
           }
         ],     
 "message": "Login Sucess"  
}

对于错误

{
 "status": "error",     
 "error": "True",   
 "data": [
           {
            "email": ["Enter a valid email address."]
            }
         ],     
 "message": "Login Failed"  
}

经过一番研究,我找到了一种方法来做到这一点。我必须覆盖ModelViewSet的默认行为以输出不同的响应。

我最初创建了一个自定义Response格式:

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')
        }

然后在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)

这将是一个更强大的解决方案,因为它可以与通用视图一起使用,而不必担心。

此外,render() 中的检查可以根据需要轻松更改(例如,在此解决方案中处理 no-2XX)。

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)

最新更新