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

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

 

posted @ 2021-04-07 15:41  盈波秋水泛清涛  阅读(98)  评论(0编辑  收藏  举报