在以前的 view 中,咱们使用了 APIView 编写处理数据的逻辑,如前文所讲 APIView 直接继承 View 是一个比较偏底层的类,尽管灵活但须要本身实现不少经常使用功能。DRF 中在 APIView 的基础上提供了一系列高级类来简化这些平常操做,好比: ListModelMixin, GenericAPIView 等。
见: https://www.django-rest-framework.org/tutorial/3-class-based-views/ Using mixins 章节。数据库
Mixins:django
mixin 类提供了 actions 用于实现基础的 view 功能。注意:这里的 action 方法并不是 http handler 如:.get(), .post() 等, 而是 create,list, retrieb,update, desdory 这样的方式是具体的实现更加灵活。api
GenericAPIView:iview
这个类继承了 APIView,并在此基础上实现了基础的 list 和 detail views。在使用 GenericAPIView 时,一般都是与 minxin 类组合使用,好比 ListAPIView 同时继承了 ListModelMixin 和 GenericAPIView(见后面例子)。
在 generics 库中,一般也都是这样的搭配,即:一个 XXXModelMixin + GenericAPIView。 其中GenericAPIView 负责数据部分,好比 queryset 和 serializer,包括 Pagination 等。 ModelMixin 则控制着如何 handle 这些数据 如: list,create, update 等。 经过两个类的互补来实现了一些特定功能。ide
类属性:函数
分页:post
过滤:ui
详见 https://www.django-rest-framework.org/api-guide/generic-views/#genericapiviewurl
ListModelMixin 例子(ModelMixin 系列中的一个):spa
该类 提供 .list(request, *args, **kwargs) 方法,来实现列出 queryset。若是 queryset 返回 http 结果 200 OK, 表示有数据,则该数据生成的列表能够用分页方法进行个性化显示。
详见: https://www.django-rest-framework.org/api-guide/generic-views/#listmodelmixin
1 from products.serializers import ProductSerializer 2 from products.models import Product 3 from rest_framework import mixins 4 from rest_framework import generics 5 6 class ProductListView(mixins.ListModelMixin, generics.GenericAPIView): 7 """注意:与 APIView 不一样的是, queryset 和 serializer 都已经包含在 GenericAPIView 中了,因此在此无需自行作代码实现 """ 8 queryset = Product.objects.all() 9 serializer_class = ProductSerializer 10 11 def get(self, request, *args, **kwargs): 12 return self.list(request, *args, **kwargs) # ListModelMixin 中包括 list 方法,该方法返回 queryset 做为 response
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
PS: For all of Views (execept viewsets) like GenericAPIView, APIView, ListAPIView ... we must provide/overwirte http methode (get, put, delete etc.)
若是 ProductListView 不须要提供 post 功能,该类能够更简单地经过 ListAPIView 来实现,具体以下:
1 class ProductListView(generics.ListAPIView): 2 # 省略以下代码 3 # def get(self, request, *args, **kwargs): 4 # return self.list(request, *args, **kwargs) 5 6 queryset = Product.objects.all() 7 serializer_class = ProductSerializer
经查阅源码,ListAPIView 的实现其实与第一个例子的逻辑几乎如出一辙,只是少了 post 函数,由于 ListAPIView 的功能仅限于展现数据,而并不是对数据进行增长或改动。
ListAPIView extra 知识点:
ListAPIView 通常用于在页面上列出全部对象详细信息,这个数据量有可能会相对庞大一些,因此须要考虑在此对输出页面进行分页配置。
在 DRF 中能够经过 setting.py 一个配置来完成分页这个复杂的功能。
见: https://www.django-rest-framework.org/api-guide/pagination/ Pagination 部分
在 setting 文件中末尾添加:
1 REST_FRAMEWORK = { 2 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', 3 'PAGE_SIZE': 10 4 }
这样就会对结果进行自动分页且每页只显示 10 个数据对象
若是目前的 Pagination 功能还不知足项目须要,可更深度地自定制分页功能。详见 Modify the pagination style 部分。
经过修改 view.py 文件
1 from rest_framework.pagination import PageNumberPagination 2 3 # 设置个性化分页功能 4 class ProductPagination(PageNumberPagination): 5 page_size = 10 6 page_size_query_param = 'page_size' 7 page_query_param = 'p' # http://127.0.0.1:8000/product/?p=1 改成了 p 而不是原来的 page 8 max_page_size = 100 9 10 class ProductListView(generics.ListAPIView): 11 queryset = Product.objects.all() 12 serializer_class = ProductSerializer 13 pagination_class = ProductPagination # 指向个性化分页配置类
注:完成以上配置后,则不须要另外对 setting 文件中的 REST_FRAMEWORK 参数进行设置。