class CourseListAPIView(ResponseMixin, generics.ListAPIView)python
2)ListAPIView
提供 get 方法,展現對象列表信息django
繼承自:GenericAPIView、ListModelMixinapi
GenericAPIView,提供了get_queryset,filter_queryset, paginate_queryset等方法便於列表視圖與詳情信息視圖的開發。瀏覽器
ListModelMixin,列表視圖擴展類,提供list(request, *args, **kwargs)方法快速實現列表視圖,返回200狀態碼。ide
執行順序this
執行CourseListAPIView.as_view()方法,DRF的APIVIEW的as_view,以及dispatch對django的request進行再次封裝,並進行認證,頻率,權限認證spa
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)
實踐rest
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