3 Django REST Framework 开发 ---- Generic Views

在以前的 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

类属性:函数

  • queryset - 用于返回 view 数据库中须要的对象。
  • serializer_class - 用于作验证,反序列化 Input,序列化 Output。
  • lookup_field - 搜索字段
  • lokup_url_kwarg - tbd

分页:post

  • pagination_class - 自定义分页

过滤:ui

  • filter_backend - 用于过滤 queryset

详见 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 参数进行设置。

相关文章
相关标签/搜索