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) ))
这样就能返回带状态的数据了,其他请求也是以此类推,重写对应的方法