rest_framework listview的执行顺序

class CourseListAPIView(ResponseMixin, generics.ListAPIView)

2)ListAPIView
提供 get 方法,展示对象列表信息

继承自:GenericAPIView、ListModelMixin

GenericAPIView,提供了get_queryset,filter_queryset, paginate_queryset等方法便于列表视图与详情信息视图的开发。

ListModelMixin,列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。

执行顺序

  1. 浏览器对路由进行访问
  2. 执行CourseListAPIView.as_view()方法,DRF的APIVIEW的as_view,以及dispatch对django的request进行再次封装,并进行认证,频率,权限认证

listview的执行顺序

class CourseListAPIView(ResponseMixin, generics.ListAPIView):
    
    
3.get请求过来,先执行get方法>>>>执行的是ListAPIView的get方法

class ListAPIView(mixins.ListModelMixin,GenericAPIView):
    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    
    
4.执行list方法>>>>ListModelMixin的list方法
class ListModelMixin(object):
    def list(self, request, *args, **kwargs):
        self.object_list = self.filter_queryset(self.get_queryset())
        page = self.paginate_queryset(self.object_list)
        if page is not None:
            serializer = self.get_pagination_serializer(page)
        else:
            serializer = self.get_serializer(self.object_list, many=True)
        return Response(serializer.data)
    
    
    
 5.执行get_queryset方法>>>>GenericAPIView(views.APIView)的get_queryset方法
	#可以通过重写get_querset方法实现过滤
    def get_queryset(self):
        if self.queryset is not None:
            return self.queryset._clone()
    ①._clone方法
    	就是复制对象
        
        
        
 6. 执行filter_queryset方法>>>>GenericAPIView(views.APIView)的filter_queryset方法
	def filter_queryset(self, queryset):
        for backend in self.get_filter_backends():
            queryset = backend().filter_queryset(self.request, queryset, self)
        return queryset
    ①get_filter_backends方法
    def get_filter_backends(self):
        if self.filter_backends is None:
            filter_backends = []
        else:
            filter_backends = list(self.filter_backends)

        if not filter_backends and self.filter_backend:
            warnings.warn(
                'The `filter_backend` attribute and `FILTER_BACKEND` setting '
                'are deprecated in favor of a `filter_backends` '
                'attribute and `DEFAULT_FILTER_BACKENDS` setting, that take '
                'a *list* of filter backend classes.',
                DeprecationWarning, stacklevel=2
            )
            filter_backends = [self.filter_backend]
        return filter_backends

    
    
  7.执行page_queryset方法>>>>GenericAPIView(views.APIView)的page_queryset方法
    
        def paginate_queryset(self, queryset, page_size=None):
            deprecated_style = False
            if page_size is not None:
                warnings.warn('The `page_size` parameter to `paginate_queryset()` '
                              'is deprecated. '
                              'Note that the return style of this method is also '
                              'changed, and will simply return a page object '
                              'when called without a `page_size` argument.',
                              DeprecationWarning, stacklevel=2)
                deprecated_style = True
            else:
                page_size = self.get_paginate_by()
                if not page_size:
                    return None

            if not self.allow_empty:
                warnings.warn(
                    'The `allow_empty` parameter is deprecated. '
                    'To use `allow_empty=False` style behavior, You should override '
                    '`get_queryset()` and explicitly raise a 404 on empty querysets.',
                    DeprecationWarning, stacklevel=2
                )

            paginator = self.paginator_class(queryset, page_size,
                                             allow_empty_first_page=self.allow_empty)
            page_kwarg = self.kwargs.get(self.page_kwarg)
            page_query_param = self.request.QUERY_PARAMS.get(self.page_kwarg)
            page = page_kwarg or page_query_param or 1
            try:
                page_number = paginator.validate_number(page)
            except InvalidPage:
                if page == 'last':
                    page_number = paginator.num_pages
                else:
                    raise Http404(_("Page is not 'last', nor can it be converted to an int."))
            try:
                page = paginator.page(page_number)
            except InvalidPage as exc:
                error_format = _('Invalid page (%(page_number)s): %(message)s')
                raise Http404(error_format % {
                    'page_number': page_number,
                    'message': str(exc)
                })

            if deprecated_style:
                return (paginator, page, page.object_list, page.has_other_pages())
            return page
        
        
        
        ①get_paginate_by
            def get_paginate_by(self, queryset=None):
                if queryset is not None:
                    warnings.warn('The `queryset` parameter to `get_paginate_by()` '
                                  'is deprecated.',
                                  DeprecationWarning, stacklevel=2)

                if self.paginate_by_param:
                    try:
                        return strict_positive_int(
                            self.request.QUERY_PARAMS[self.paginate_by_param],
                            cutoff=self.max_paginate_by
                        )
                    except (KeyError, ValueError):
                        pass

                return self.paginate_by
            
        paginate_by = api_settings.PAGINATE_BY
 


8.分页的话,执行get_pagination_serializer >>>>GenericAPIView(views.APIView)的 get_pagination_serializer

	def get_pagination_serializer(self, page):
        class SerializerClass(self.pagination_serializer_class):
            class Meta:
                object_serializer_class = self.get_serializer_class()
        pagination_serializer_class = SerializerClass
        context = self.get_serializer_context()
        return pagination_serializer_class(instance=page, context=context)
    
    ①get_serializer_context
    提供给序列化器额外的参数
     def get_serializer_context(self):
        return {
            'request': self.request,
            'format': self.format_kwarg,
            'view': self
        }
    
    
9.不分页的话 get_serializer
   def get_serializer(self, instance=None, data=None, files=None, many=False,
                       partial=False, allow_add_remove=False):
        serializer_class = self.get_serializer_class()
        context = self.get_serializer_context()
        return serializer_class(instance, data=data, files=files,
                                many=many, partial=partial,
                                allow_add_remove=allow_add_remove,
                                context=context)
    
 

实践

from courseact.rest.mixin import ResponseMixin
from rest_framework import generics
from courseact.rest.pagination import CommonPaginationSerializer

class ClassListAPIView(ResponseMixin, generics.ListAPIView):
    pagination_serializer_class = CommonPaginationSerializer
    queryset = Klass.objects.all()
    serializer_class = KlassListSerializer

    ③def get_serializer_context(self):
        print("3")
        user = self.request.user
        return {'user': user}#user = self.context['user']后续序列化器使用

    ①def get_queryset(self):#获取对象列表,可以进行分组,排序操作
        print("1")
        return self.queryset

    ②def filter_queryset(self, queryset):#对对象列表进行筛选
        print("2")
        data = self.request.GET.dict()
        center = get_center_for_user(self.request.user)
        queryset = queryset.filter(center=center, academic_year=int(data.get("academic_year")))
        return queryset

posted @ 2019-09-18 10:28  robertzhou  阅读(324)  评论(0编辑  收藏  举报