zoukankan      html  css  js  c++  java
  • 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
    
    
  • 相关阅读:
    [#]
    Windows 下配置 ApacheBench (AB) 压力测试
    [转载]
    Nginx 系列教程
    设置外接显示器顺序(哪个在左,哪个在右)的方法
    [.Net] 一句话Linq(递归查询)
    [Xamarin]
    [SVN]
    [SQL SERVER]
    [Oracle]
  • 原文地址:https://www.cnblogs.com/robert-zhou/p/11540099.html
Copyright © 2011-2022 走看看