概述

在DRF中,允许在一个类中组合一组相关视图的逻辑,称为ViewSets。比如通过通用视图,可以定义列表视图、详情视图等等,但每个视图位于不同的类中,而通过ViewSets则可以将多个视图放在同一个类中。

ViewSets也是一种基于类的视图,只不过和APIView不同的是,它并不提供如get()、post()等和HTTP请求相对应的方法,而提供的是如list()、create()这样的操作方法。

在配置ViewSets的URL时,一般不会显示进行配置,而是使用Routers类来注册ViewSets,Routers会自动确定URL格式。

Router可以将请求和视图自动进行匹配,并映射相应的处理逻辑。

如果我们使用的是ViewSets而非View,那么我们就没必要自己去配置每个View对应的Url了,直接使用Router注册一个视图集,让Router来完成剩下的工作。

1.viewsets类

使用viewsets时需要导入所在模块:

from rest_framework import viewsets

所有的viewsets类都直接或间接的继承于ViewSetMixin这个基类。目前viewsets相关类有包中有四个类,接下来我们逐一进行总结.

1.1.ViewSet

ViewSets继承了ViewSetMixin和APIView,因此具有APIView的一些属性,如permission_class和authentication_classes属性,但没有实现具体的动作,所以在平时开发时,会很少用到它。该类源码如下:

class ViewSet(ViewSetMixin, views.APIView):
"""
The base ViewSet class does not provide any actions by default.
"""
pass

1.2.GenericViewSet

GenericViewSet继承于ViewSetMixin和GenericAPIView,因此具有GenericAPIView拥有的一些属性和方法,如serializer_class、queryset、get_queryset()、get_object()等其他方法和属性,但同样也没有提供操作请求的动作实现,因此该类经常和其他generic包下的具体通用视图一起使用,如:

class Show(viewsets.GenericViewSet,
generics.ListCreateAPIView):
# ListCreateAPIView将list()和create()方法和get(),post()进行了绑定 serializer_class = SnippetSerializer
queryset = Snippet.objects.all()

该类源码如下:

class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
"""
The GenericViewSet class does not provide any actions by default,
but does include the base set of generic view behavior, such as
the `get_object` and `get_queryset` methods.
"""
pass

1.3.ModelViewSet

该类继承于GenericViewSet,并通过混合各种Mixin类的行为,实现了各种动作的实现。该类源码如下:

class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
"""
A viewset that provides default `create()`, `retrieve()`, `update()`,
`partial_update()`, `destroy()` and `list()` actions.
"""
pass

因此,通过一个ModelViewSet就可以完成包含列表视图、详情视图等多个视图和请求的操作。

1.4.ReadOnlyModelViewSet

该类继承于GenericViewSet,同时混合了RetrieveModelMixin和ListModelMixin,因此可以用于展示列表视图和详情视图,所以是”只读”的.该类源码如下:

class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
mixins.ListModelMixin,
GenericViewSet):
"""
A viewset that provides default `list()` and `retrieve()` actions.
"""
pass

对整个viewsets包中的类进行总结之后,下面开始总结下如果通过Router给ViewSets配置URL。

2.Router

在学习ViewSets和Router之前,我们对一个View配置Url是通过如下方式进行的:

urlpatterns = [
path('show/', views.ShowList.as_view()), # 用于列表视图
path('show/<pk>', views.ShowDetail.as_view()) #用于详情视图
]

可以看到,这种方式确实挺麻烦的,针对于不同的View,都需要单独进行配置。

如果是通过ViewSets实现的View,那么通过Router就可以自动配置url了,我们只需给Router注册一个ViewSets,其他的什么都不用管。

使用Router时需要导入所在包:

from rest_framework import routers

如:

from rest_framework.routers import DefaultRouter

router = DefaultRouter()
# 给router注册ShowViewSet
router.register('show', views.ShowViewSet, base_name='show') urlpatterns = [
path('admin/', admin.site.urls),
path('', include(router.urls)),
]

其中,register()方法用来注册一个ViewSets,其所需参数如下:

  • 1.prefix:用于这组路由的URL前缀,该参数必须指定;
  • 2.viewset:ViewSets类,该参数必须指定;
  • 3.base_name:该参数可选,用于指定创建URL的名称,如果未指定,则默认使用viewsets中的queryset属性自动生成,因此,如果viewsets中没有声明queryset属性,则该参数必须设置。

当注册之后,DRF根据具体的viewsets为我们自动生成对个URL,如存在以下viewsets和Router:

# views.py中:

from rest_framework import viewsets

class ShowViewSet(viewsets.ModelViewSet):

    serializer_class = SnippetSerializer
queryset = Snippet.objects.all() # urls.py中:
from rest_framework.routers import DefaultRouter router = DefaultRouter()
router.register('show', views.Show, base_name='show') urlpatterns = router.urls

生成的URL格式如下:

   ^show/$ [name='show-list']
^show/(?P<pk>[^/.]+)/$ [name='show-detail']

目前在routers包中有两个类:SimpleRouter和DefaultRouter,DefaultRouter继承于SimpleRouter,这两个类没有太大区别,只不过DefaultRouter中包含一个其根API视图,它返回包含所有列表视图的超链接。这么说可能不太理解,还是用上面的例子直接对比下两个Router吧:

首先是DefaultRouter来注册一个ViewSets,通过浏览器访问项目根Url:

然后用SimpleRouter试试:

这样一比较,效果一目了然,无需多费口舌。

下面这个表格中记录了URL相关的信息,来自DRF官网:

URL Style HTTP Method Action URL Name
{prefix}/ GET list {basename}-list
POST create
{prefix}/{url_path}/ GET, or as specified by `methods` argument `@action(detail=False)` decorated method {basename}-{url_name}
{prefix}/{lookup}/ GET retrieve {basename}-detail
PUT update
PATCH partial_update
DELETE destroy
{prefix}/{lookup}/{url_path}/ GET, or as specified by `methods` argument `@action(detail=True)` decorated method {basename}-{url_name}

3.总结

虽然使用ViewSets可以将多个视图创建在一个类中,但这是由于这个原因,使用viewsets不如单独构建视图那么明确。因此在设计代码时,因通过具体场景选择是使用generic view呢,还是viewsets呢(不过大多数场景下,我还是选择ViewSets)。

四,ViewSets和Routers的更多相关文章

  1. Django编写RESTful API(六):ViewSets和Routers

    欢迎访问我的个人网站:www.comingnext.cn 前言 在本系列的文章中,我在第一篇和第二篇文章中写的编写Django视图时,使用的都是基于函数的方法,并且每个视图函数之前都会加一个djang ...

  2. django rest framwork教程之 viewsets和routers

    ViewSets 和Routers REST框架包括一个用于抽象处理的ViewSets,允许开发人员集中精力对API的状态和交互进行建模,并根据常见约定自动处理URL构造. Viewset 类和 Vi ...

  3. django drf viewsets和routers

    1.定义VIew from django.shortcuts import render from rest_framework.views import APIView from rest_fram ...

  4. Django REST framework+Vue 打造生鲜超市(四)

    五.商品列表页 5.1.django的view实现商品列表页 (1)goods/view_base.py 在goods文件夹下面新建view_base.py,为了区分django和django res ...

  5. drf框架 - 视图家族 | GenericAPIView | mixins | generics | viewsets

    视图家族 view:视图 generics:工具视图 mixins:视图工具集 viewsets:视图集 学习曲线: APIView => GenericAPIView => mixins ...

  6. drf 教程

    1, 序列化 Serialization 创建一个新环境 在做其他事之前,我们会用virtualenv创建一个新的虚拟环境.这将确保我们的包配置与我们正在工作的其他项目完全隔离. virtualenv ...

  7. Django REST FrameWork中文教程2:请求和响应

    从这一点开始,我们将真正开始覆盖REST框架的核心.我们来介绍几个基本的构建块. 请求对象REST框架引入了Request扩展常规的对象HttpRequest,并提供更灵活的请求解析.Request对 ...

  8. Django REST framework 中文教程1:序列化

    建立环境 在我们做任何事情之前,我们将使用virtualenv创建一个新的虚拟环境.这将确保我们的包配置与我们正在开展的任何其他项目保持良好的隔离. virtualenv envsource env/ ...

  9. 从django的序列化到rest-framework 序列化

    1.利用Django的view实现返回json数据 from django.views.generic import View from goods.models import Goods class ...

随机推荐

  1. PHP读取txt文件到数组

    $file_path = "test.txt"; if(file_exists($file_path)){ $file_arr = file($file_path); for($i ...

  2. python学习笔记_week14

    Web框架本质 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. s1 import socket def handle_reques ...

  3. ck

    ck

  4. python中的expandtabs、\t

    expandtabs()将tab转换成空格,默认1个tab转成8个空格,\t制表符代表一个tab,我们也可以自定义转换成几个空格 举个例子: 1 a = "hello\tworld" ...

  5. Http协议基础知识

    r equest POST https://re.csdn.net/csdnbi HTTP/1.1方法 url/uri 协议的版本号 1.1Host: re.csdn.netConnection: k ...

  6. Android 开发第三步-问题解析

    因为这个问题,困扰了好久 最后找到了最根本的问题,当时是因为没有R.java为什么没有? 是因为布局出现了错误,在一篇百度经验中找到了怎样解决 https://jingyan.baidu.com/ar ...

  7. 简单ATM机功能实现及感想

    感想:  在那一天下午气喘吁吁的上了六楼 在建民的课上 都要带电脑 第一次上这样的课,每一次都是个段子 ,这一次考试是学前考试,什么也不知道 ,但是通过百度, 发现JAVA有很多还都和C语言相似的地方 ...

  8. linux常用命令以及快捷键

    find命令查找某些文件并将其拷贝到指定目录 [root@host lib]# find -name "*hbase*.jar" |xargs -i cp {}  /root/aa ...

  9. python大法好——变量、常量、input()、数据类型、字符串、格式化输出、运算符、流程控制语句、进制、字符编码

    python基础知识 1.变量 变量:把程序运算的中间结果临时存到内存里,以备后面的代码可以继续调用. 作用:A.存储数据. B.标记数据. 变量的声明规则: A:变量名只能是字母,数字或下划线任意组 ...

  10. ssm学习的第一个demo---crm(2)

    第四步:                  别名不区分大小写:入参为基本类型,#{可以随便写} 把静态资源(jsp.css.js.fonts)导入到项目中 第五步: 创建Contrller类(和普通j ...