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:

mixin 类提供了 actions 用于实现基础的 view 功能。注意:这里的 action 方法并非 http handler 如:.get(), .post() 等, 而是 create,list, retrieb,update, desdory 这样的方式是具体的实现更加灵活。

GenericAPIView:

这个类继承了 APIView,并在此基础上实现了基础的 list 和 detail views。在使用 GenericAPIView 时,通常都是与 minxin 类组合使用,比如 ListAPIView 同时继承了 ListModelMixin 和 GenericAPIView(见后面例子)。
在 generics 库中,通常也都是这样的搭配,即:一个 XXXModelMixin + GenericAPIView。 其中GenericAPIView 负责数据部分,比如 queryset 和 serializer,包括 Pagination 等。 ModelMixin 则控制着如何 handle 这些数据 如: list,create, update 等。 通过两个类的互补来实现了一些特定功能。

类属性:

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

分页:

  • pagination_class - 自定义分页

过滤:

  • filter_backend - 用于过滤 queryset

详见 https://www.django-rest-framework.org/api-guide/generic-views/#genericapiview

ListModelMixin 例子(ModelMixin 系列中的一个):

该类 提供 .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 的body
13 
14     def post(self, request, *args, **kwargs):
15         return self.create(request, *args, **kwargs)

如果 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 参数进行设置。

猜你喜欢

转载自www.cnblogs.com/crazy-chinese/p/9828113.html