Django(58)viewsets视图集详解
2021-06-10 16:57
1116 查看
前言
ViewSet只是一种基于类的视图,它不提供任何方法处理程序(如
.get()或
.post()),而是提供诸如
.list()和
.create()之类的操作。
ViewSet的方法处理程序仅使用
.as_view()方法绑定到完成视图的相应操作。 通常不是在
urlconf中的视图集中显示注册视图,而是要使用路由类注册视图集,该类会自动为你确定
urlconf。
源码分析
我们首先看一下
viewsets.py文件的源码结构,如下图 我们可以看到有5个类
- ViewSetMixin
- ViewSet:继承自
ViewSetMixin
和APIView
- GenericViewSet:继承自
ViewSetMixin
和GenericAPIView
- ReadOnlyModelViewSet:继承自
RetrieveModelMixin
、ListModelMixin
、GenericViewSet
- ModelViewSet:继承自5大
mixins
工具类和GenericViewSet
ViewSetMixin
通过上述代码结构分析,我们了解到只要知道
ViewSetMixin是干嘛的,其他的类都继承于它。从源码中我们知道,
ViewSetMixin重写了
as_view()方法,源码如下:
def as_view(cls, actions=None, **initkwargs): """ 由于基于类的视图围绕实例化视图创建闭包的方式,我们需要完全重新实现`.as_view`,并稍微修改创建和返回的视图函数。 对于某些路由配置,initkwargs 的名称和描述可能会被明确覆盖,例如,额外操作的名称。 """ # 名称和描述 initkwargs 可能会被显式覆盖 cls.name = None cls.description = None # 后缀 initkwarg 保留用于显示视图集类型。如果提供了名称,则此 initkwarg 应该无效。 cls.suffix = None cls.detail = None # 设置 basename 允许视图反转其操作 url。该值由路由器通过 initkwargs 提供。 cls.basename = None # actions必须不能为空,否则报错 if not actions: raise TypeError("The `actions` argument must be provided when " "calling `.as_view()` on a ViewSet. For example " "`.as_view({'get': 'list'})`") # 清理关键字参数 for key in initkwargs: if key in cls.http_method_names: raise TypeError("You tried to pass in the %s method name as a " "keyword argument to %s(). Don't do that." % (key, cls.__name__)) if not hasattr(cls, key): raise TypeError("%s() received an invalid keyword %r" % ( cls.__name__, key)) # name和suffix是互斥的 if 'name' in initkwargs and 'suffix' in initkwargs: raise TypeError("%s() received both `name` and `suffix`, which are " "mutually exclusive arguments." % (cls.__name__)) def view(request, *args, **kwargs): self = cls(**initkwargs) if 'get' in actions and 'head' not in actions: actions['head'] = actions['get'] self.action_map = actions # 将方法绑定到actions, 这是与标准视图不同的一点 for method, action in actions.items(): handler = getattr(self, action) setattr(self, method, handler) self.request = request self.args = args self.kwargs = kwargs return self.dispatch(request, *args, **kwargs) update_wrapper(view, cls, updated=()) update_wrapper(view, cls.dispatch, assigned=()) view.cls = cls view.initkwargs = initkwargs view.actions = actions return csrf_exempt(view)
从上述源码中了解到,
ViewSetMixin重写了
as_view方法,
as_view是将请求的方法绑定到了
actions
ViewSet
class ViewSet(ViewSetMixin, views.APIView): """ 默认情况下,基本 ViewSet 类不提供任何操作。 """ pass
ViewSet继承了
ViewSetMixin和
APIView,增删改查需要我们自己定义
GenericViewSet
class GenericViewSet(ViewSetMixin, generics.GenericAPIView): """ GenericViewSet 类默认不提供任何操作,但包含通用视图行为的基本集,例如`get_object` 和`get_queryset` 方法。 """ pass
GenericViewSet类相比
ViewSet,包含了一些视图行为的通用方法
视图集特点
- 视图集都是优先继承
ViewSetMixin
类,再继承一个视图类(GenericAPIView或APIView)
ViewSetMixin
提供了重写的as_view()
方法,继承视图集的视图类,配置路由时调用as_view()
必须传入 请求-函数名 映射关系字典eg: path('v1/books/<int:pk>/', views.BookGenericViewSet.as_view({"get": "my_get_obj"}))
GenericAPIView与APIView 作为两大继承视图的区别
GenericViewSet
和ViewSet
都继承了ViewSetMixin
,as_view
都可以配置 请求-函数 映射GenericViewSet
继承的是GenericAPIView
视图类,用来完成标准的model
类操作接口ViewSet
继承的是APIView
视图类,用来完成不需要model
类参与,或是非标准的model
类操作接口post
请求在标准的model
类操作下就是新增接口,登陆的post
不满足post
请求验证码接口,不需要model
类的参与 案例:登陆的post
请求,并不是完成数据的新增,只是用post
提交数据,得到的结果也不是登陆的用户信息,而是登陆的认证信息
ReadOnlyModelViewSet
class ReadOnlyModelViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, GenericViewSet): """ 提供默认`list()` 和`retrieve()` 操作的视图集。 """ pass
ModelViewSet
class ModelViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin, GenericViewSet): """ 一个提供默认 `create()`、`retrieve()`、`update()`、`partial_update()`、`destroy()` 和 `list()` 操作的视图集。 """ pass
实战案例
视图函数如下
class StudentViewSets(viewsets.ModelViewSet): queryset = Student.objects.all() serializer_class = StudentModelSerializer def my_get(self, request, *args, **kwargs): response = self.retrieve(request, *args, **kwargs) return APIResponse(results=response.data) def my_list(self, request, *args, **kwargs): response = self.list(request, *args, **kwargs) return APIResponse(results=response.data)
我们继承自
ModelViewSet,自带5个
mixins工具,我们定义了2个查询方法,然后在
urls中配置
urlpatterns = [ path('v2/student/<int:pk>/', views.StudentViewSets.as_view({"get": "my_get"})), path('v2/student/', views.StudentViewSets.as_view({"get": "my_list"})), ]
在
as_view中添加了
get请求方式的方法,有
pk调用
my_get代表单查,没有
pk调用
my_list代表群查,这样写的原因就是我们的
StudentViewSets继承了
ViewSetMixin。
相关文章推荐
- DjangoRestFramework系列教程(6):视图集viewsets和路由器router
- Django 之REST framework学习6:视图集合类和路由器(ViewSets & Routers)
- django学习日志(View视图)第四部分:Request对象和Response对象
- Django之view视图处理(FBV,CBV,装饰器,前后端交互各种数据类型和响应,请求头相关信息)【交互篇二】
- python3开发进阶-Django视图(View)的常见用法
- Android中View(视图)绘制不同状态背景图片原理深入分析以及StateListDrawable使用详解
- django基础(四)详解Views视图层
- Android中View(视图)绘制不同状态背景图片原理深入分析以及StateListDrawable使用详解
- iOS开发-轻松学会封装自定义视图view(自定义弹框封装详解)
- 详解Django通用视图中的函数包装
- 在Django的视图(View)外使用Session的方法
- Django框架学习 — 8.1视图详解 -- url路由
- Android开发之自定义View(视图)用法详解
- UICollectionView 集合视图详解
- Django源码分析3:处理请求wsgi分析与视图View
- django 类视图的使用方法详解
- 编程之路之数据库mysql(七)- mysql视图(view)和事务(transaction)详解
- 详解Django框架中的视图级缓存
- Oracle materizlized view Study (3) ---详解物化视图日志
- Django中的url与视图详解(3)