zoukankan      html  css  js  c++  java
  • django rest framework响应数据的源码分析

    由于 rest framework自带的接口没有响应的状态码,所以我一直都想给返回的数据里面加上接口请求的状态码,于是今天特地去翻了一下源码

    由于我用的视图类ModelViewSet继承了rest_framework.mixins.CreateModelMixin,rest_framework.mixins.RetrieveModelMixin,rest_framework.mixins.UpdateModelMixin,

    rest_framework.mixins.DestroyModelMixin,rest_framework.mixins.ListModelMixin,rest_framework.rest_framework.viewsets.GenericViewSet类

    在mixins.py中定义了5种请求的类,他们各自定义了对应请求的方法,返回相应的数据。

    class ModelViewSet(mixins.CreateModelMixin,
                       mixins.RetrieveModelMixin,
                       mixins.UpdateModelMixin,
                       mixins.DestroyModelMixin,
                       mixins.ListModelMixin,
                       GenericViewSet):
        """
        A viewset that provides default `create()`, `retrieve()`, `update()`,
        `partial_update()`, `destroy()` and `list()` actions.
        """
        pass
    
    class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
        """
        The GenericViewSet class does not provide any actions by default,
        but does include the base set of generic view behavior, such as
        the `get_object` and `get_queryset` methods.
        """
        pass

    当使用list方法获取数据的时候他会对数据做分页处理

    class ListModelMixin:
        """
        List a queryset.
        """
        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)
            return Response(serializer.data)

    在这里的get_paginated_response方法在GenericViewSet类中做了定义

    class GenericAPIView(views.APIView):
          def get_paginated_response(self, data):
            """
            Return a paginated style `Response` object for the given output data.
            """
            assert self.paginator is not None
            return self.paginator.get_paginated_response(data)
        @property
        def paginator(self):
            """
            The paginator instance associated with the view, or `None`.
            """
            if not hasattr(self, '_paginator'):
                if self.pagination_class is None:
                    self._paginator = None
                else:
                    self._paginator = self.pagination_class()
            return self._paginator

    这里的paginator方法中调用的是我们在视图中定义的分页类,如:

    class DefaultPagination(PageNumberPagination):
        page_size = 10

    这里的继承了PageNumberPagination类

    class PageNumberPagination(BasePagination):
        def get_paginated_response(self, data):
            return Response(OrderedDict([
                ('count', self.page.paginator.count),
                ('next', self.get_next_link()),
                ('previous', self.get_previous_link()),
                ('results', data)
            ]))

    这里就返回了我们前端接口中获取的数据结构了

    所以我们就可以定义一个方法get_paginated_status_response在BasePagination类中,然后把PageNumberPagination继承BasePagination类

    class BasePagination(PageNumberPagination):
        page_size_query_param = 'pagesize'
        page_query_param = 'page'
        max_page_size = 1000
    
        def get_paginated_status_response(self, data,status=1):
            return Response(OrderedDict([
                ('count', self.page.paginator.count),
                ('next', self.get_next_link()),
                ('previous', self.get_previous_link()),
                ('results', data),
                ('status',status)
            ]))

    定义一个继承ModelViewSet类的派生类,并重写get_paginated_response方法及list方法

    class BaseView(ReturnFormatMixin, viewsets.ModelViewSet):
        queryset = None
        serializer_class = None
        permission_classes = []
        # 分页
        pagination_class = DefaultPagination
        search_fields = []
        def get_paginated_status_response(self, data,status):
            """
            Return a paginated style `Response` object for the given output data.
            """
            assert self.paginator is not None
            return self.paginator.get_paginated_response(data,status)
        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)
            return Response(
                 OrderedDict(
                     ('results',serializer.data),
                     ('status',1)
                 ))        

    这样就能返回带状态的数据了,其他请求也是以此类推,重写对应的方法

  • 相关阅读:
    【 js 基础 】【 源码学习 】源码设计 (更新了backbone分析)
    【 js 基础 】【读书笔记】作用域和闭包
    【 js 基础 】【 源码学习 】 setTimeout(fn, 0) 的作用
    入职一个月快速熟悉大型Vue项目经验感想
    Git 实习一个月恍然大悟合集
    不断更新:整理常见的闭包问题
    (转)当margin-top、padding-top的值为百分比时是如何计算的?
    2019年8月面试腾讯前端开发实习生记录
    vue-cli2.X中引入高德地图,将其设为全局对象
    学习整理:用webpack4.x构建基本项目
  • 原文地址:https://www.cnblogs.com/arrow-kejin/p/14628045.html
Copyright © 2011-2022 走看看