- Title(EN): Django REST Framework Learning Notes (10): Generic Views, MixIns, ViewSets and Routers
 - Author: dog2
 
基本信息
- 源码
- rest_framework.views
 - rest_framework.generics
 - rest_framework.viewsets
 - rest_framework.routers
 
 - 官方文档
- API Guide - Generic views
 - API Guide - ViewSets
 - API Guide - Routers
 
 - 本文demo代码Github
 
AIPView - API视图类
APIView是Django REST Framework提供的所有视图的基类,继承自Django的View父类。
与Django View的不同
- 传入到视图方法中的是REST framework的
Request对象,而不是Django的HttpRequeset对象 - 视图方法可以返回REST framework的
Response对象,视图会为响应数据设置(render)符合前端要求的格式 - 任何
APIException异常都会被捕获到,并且处理成合适的响应信息 - 在进行
dispatch()分发前,会对请求进行身份认证、权限检查、流量控制 
重要类属性
AIPView有如下可设置的重要类属性:
authentication_classes:列表或元祖,身份认证类permissoin_classes:列表或元祖,权限检查类throttle_classes:列表或元祖,流量控制类
示例代码
在APIView中仍有get(),post()等其他请求方式的方法
1  | from rest_framework.views import APIView  | 
GenericAPIView - 通用API视图类
通用API视图类GenericAPIView继承自APIView,完全兼容APIView,主要增加了操作序列化器和数据库查询的方法,作用是为下面Mixin扩展类的执行提供基础类支持。通常在使用时,可以配合一个或多个Mixin扩展类。
GenericAPIView比APIView多了什么
get_queryset():从类属性queryset中获得model的queryset数据。群操作就走get_queryset()方法(包括群查,群增等)。get_object():从类属性queryset中获得model的queryset数据,再通过有名分组pk确定唯一操作对象。单操作就走get_object()方法(包括单查,单增等)。get_serializer():从类属性serializer_class中获得serializer的序列化类。
重要类属性
GenericAPIView有如下可设置的重要类属性:
- 列表视图与详情视图共用
queryset:指明视图需要的数据(model查询数据)permissoin_classes:指明视图使用的序列化器
 - 列表视图使用
pagination_class:指定分页控制类filter_backends:指定过滤控制后端
 - 详情页视图使用
lookup_field:自定义主键,有名分组的查询,默认是pklookup_url_kwarg:查询单一数据时url中的参数关键字名称,默认与look_field相同
 
重要类方法
get_queryset():从类属性queryset中获得model的queryset数据get_object():从类属性queryset中获得model的queryset数据,再通过有名分组pk来确定唯一操作对象get_serializer():从类属性serializer_class中获得serializer的序列化类,主要用来提供给Mixin扩展类使用
get_serializer 源码
1  | def get_serializer(self, *args, **kwargs):  | 
示例代码
视图层 views.py
1  | class BookGenericAPIView(GenericAPIView):  | 
路由层 urls.py
1  | urlpatterns = [  | 
xxxModelMixin - 视图类的模型工具集
作用
- 提供了几种后端视图(对数据资源的增删改查)处理流程的实现,如果需要编写的视图属于这五种,则视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量。
 mixins有五个工具类文件,一共提供了五个工具类,六个工具方法:单查、群查、单增、单删、单整体改、单局部改
使用
- 继承工具类可以简化请求函数的实现体,但是必须继承
GenericAPIView,需要GenericAPIView类提供序列化器与数据库查询的方法(见上方GenericAPIView基类知识点) - 工具类的工具方法返回值都是
Response类型对象,如果要格式化数据格式再返回给前台,可以通过response.data拿到工具方法返回的Response类型对象的响应数据 
五大模型工具类
ListModelMixin 群查
- 列表视图扩展类,提供
list方法快速实现查询视图 - 返回
200状态码 - 除了查询,该
list方法会对数据进行过滤和分页 
CreateModelMixin 单增
- 创建视图扩展类,提供
create方法快速创建资源的视图,成功返回201的状态码 - 没有群增的方法,需要自己手动写
 
RetrieveModelMixin 单查
- 详情视图扩展类,提供
retrieve方法,可以快速实现返回一个存在的数据对象 
UpdateModelMixin 更新/修改
- 更新视图扩展类,提供
update方法,可以快速实现更新一个存在的数据对象,同时也提供partial_update方法,可以实现局部更新 - 只有单整体改和单局部改,没有群整体改和群局部改
 
DestoryModelMixin 删除
- 删除视图扩展类,提供
destory方法,可以快速实现删除一个存在数据对象 - 一般不怎么用到,因为实际开发中并不会真的删除数据,而是修改是否可用的标记
 
示例代码
视图层 views.py
1  | from rest_framework.mixins import ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin  | 
路由层 urls.py
1  | urlpatterns = [  | 
xxxAPIView - 功能性子视图类
功能性子视图类继承了GenericAPIView和各种Mixins工具类
- 功能性视图类都是
GenericAPIView的子类,且不同的子类继承了不同的工具类 - 工功能性视图类的功能可以满足需求,只需要继承工具视图,并且提供
queryset与serializer_class即可 
各大功能子视图类
一表胜千言:
| 视图 | 作用 | 请求类型 | 父类 | 
|---|---|---|---|
| ListAPIView | 查询多条数据 | get | GenericAPIView  ListModelMixin  | 
| CreateAPIView | 新增一条数据 | post | GenericAPIView  CreateModelMixin  | 
| RetrieveAPIView | 查询一条数据 | get | GenericAPIView  RetrieveModelMixin  | 
| UpdateAPIView | 修改一条数据 | put  patch  | 
GenericAPIView  UpdateModelMixin  | 
| DestroyAPIView | 删除一条数据 | delete | GenericAPIView  DestroyModelMixin  | 
| RetrieveUpdateAPIView | 单查  更新一条数据  | 
get put patch  | 
GenericAPIView RetrieveModelMixin UpdateModelMixin  | 
| RetrieveUpdateDestroyAPIView | 单查 更新 删除一条数据  | 
get put patch delete  | 
GenericAPIView RetrieveModelMixin UpdateModelMixin DestroyModelMixin  | 
| ListCreateAPIView | 群查 更新一条  | 
get post  | 
GenericAPIView ListModelMixin mixins.CreateModelMixin  | 
示例代码
视图层 views.py
1  | from rest_framework.generics import ListCreateAPIView, UpdateAPIView  | 
路由层 urls.py
1  | urlpatterns = [  | 
xxxViewset - 视图集
常用视图集父类
ViewSetMixin
ViewSetMixin主要是自定义了as_view方法,使可以通过其参数指定 HTTP_METHOD与函数的映射关系,如 view = MyViewSet.as_view({'get': 'list', 'post': 'create'})
ViewSet
继承自APIView和ViewSetMixin,没有提供任何方法,需要自己写
GenericViewSet
继承GenericAPIView和ViewSetMixin,其中GenericAPIView提供了基础方法,可以直接搭配Mixin扩展类使用,因此比较常用
ModelViewSet
继承GenericViewset,但同时也包括ListModelMixin、CreateModelMixin等mixin扩展类
源码分析
- 视图集都是默认优先继承
ViewSetMixin类,再继承一个视图类(GenericAPIView或APIView) ViewSetMixin提供了重写的as_view()方法,继承视图集的视图类,配置路由时调用as_view()必须传入 请求名-函数名 映射关系字典
例如:
1  | path('v5/books/', views.BookGenericViewSet.as_view({'get': 'my_get_list'})),  | 
表示get请求会交给my_get_list视图函数处理
GenericViewSet 示例代码
路由层 urls.py
1  | urlpatterns = [  | 
视图层 views.py
1  | from rest_framework.viewsets import GenericViewSet  | 
GenericViewSet与ViewSet
异同
GenericViewSet和ViewSet都继承了ViewSetMixin,as_view都可以配置 请求-函数 映射GenericViewSet继承的是GenericAPIView视图类,用来完成标准的model类操作接口ViewSet继承的是APIView视图类,用来完成不需要model类参与,或是非标准的model类操作接口,如post请求在标准的model类操作下就是新增接口,登陆的post不满足。登陆的post请求,并不是完成数据的新增,只是用post提交数据,得到的结果也不是登陆的用户信息,而是登陆的认证信息post请求验证码的接口,不需要model类的参与
源码
- GenericViewSet
 
1  | # viewsets.py  | 
- ViewSet
 
1  | 
  | 
ModelViewSet 示例代码
路由层 urls.py
1  | urlpatterns = [  | 
视图层 views.py
1  | class BookModelViewSet(ModelViewSet):  | 
路由组件
因为具有局限性,所以在开发复杂接口时并不是首选。
示例代码如下:
1  | from django.urls import path, include  | 
总结
一图胜千言,非原创,均来自网络: