Skip to main content
 首页 » 编程设计

python之所有响应的 Django REST 框架自定义格式

2025年01月19日27bluestorm

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

Django==1.10 djangorestframework==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"   
} 

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

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) 

在 View 中我使用我的自定义 View 集

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_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)