用于所有响应的 Django REST 框架自定义格式

Chr*_*ose 8 python authentication django angularjs django-rest-framework

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

Django==1.10 djangorestframework==3.7.1

我需要来自 DRF 的所有响应都采用以下格式。

{
 "status": "",  //  200,400,.....etc
 "error": "",   //  True, False
 "data": [],    //  data
 "message": ""  //  Success messages
}
Run Code Online (Sandbox Code Playgroud)

目前它在

[
    {
        "id": 1,
        "name": ""
    },
    {
        "id": 2,
        "name": ""
    }
]
Run Code Online (Sandbox Code Playgroud)

它应该是

{
     "status": "200",   
     "error": "False",      
     "data": [
               {
                   "id": 1,
                   "name": ""
                },
                {
                   "id": 2,
                   "name": ""
                }
            ],    
     "message": "Success"  
}
Run Code Online (Sandbox Code Playgroud)

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

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)
Run Code Online (Sandbox Code Playgroud)

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

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)
Run Code Online (Sandbox Code Playgroud)

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

'rest_framework.authtoken',
'rest_auth',
Run Code Online (Sandbox Code Playgroud)

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

{
    "key": "e642efd0b78e08b57bf34fa999f49b70a7bfe21a"
}
Run Code Online (Sandbox Code Playgroud)

相反,我需要这个。

{
 "status": "200",   
 "error": "False",      
 "data": [
          {
           "token":{ 
                     "key":"e642efd0b78e08b57bf34fa999f49b70a7bfe21a"
                    }
           }
         ],     
 "message": "Login Sucess"  
}
Run Code Online (Sandbox Code Playgroud)

对于错误

{
 "status": "error",     
 "error": "True",   
 "data": [
           {
            "email": ["Enter a valid email address."]
            }
         ],     
 "message": "Login Failed"  
}
Run Code Online (Sandbox Code Playgroud)

Chr*_*ose 7

经过一番研究,我找到了一种方法来做到这一点。我必须覆盖 的默认行为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')
        }
Run Code Online (Sandbox Code Playgroud)

然后在以下每个方法中使用此自定义格式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)
Run Code Online (Sandbox Code Playgroud)

  • 我有同样的问题,但已经用这个答案解决了:/sf/answers/1429854541/ 它使用了更通用的方法!也许它有帮助 (4认同)