前言
在Django REST framework(DRF)的世界里,ViewSet和ModelViewSet是两大基石,它们为开发者提供了简洁、高效的方式来构建API视图。与此同时,DefaultRouter和SimpleRouter作为路由映射的利器,为API提供了清晰的访问路径。
本文将带你深入了解ViewSet和ModelViewSet的概念、功能及用法,并解析DefaultRouter与SimpleRouter的区别。
一、ViewSet
1. 视图集是什么
在DRF中,
ViewSet
是一种将多个视图逻辑整合到一个类中的方式。它不再像传统的Django视图那样使用get()
,post()
,put()
,delete()
等方法来处理HTTP请求,而是定义一系列Action动作(如list()
,retrieve()
,create()
,update()
,destroy()
等)来处理不同的HTTP请求。视图集 简单来说就是一群视图逻辑操作的功能合集,并可采用 路由映射 的方式进行功能选择,编写的内置逻辑方法不再是使用请求命名,而是使用功能来进行命名。
2. action 是什么
视图集类不再实现 get 、post 等方法,而是实现动作 action 如 list 、create 等,视图集 只在使用 as_view 方法的时候,才会将 action 动作与具体请求方式对应上
例如,下面编写的最基本的视图集:
# views.py from django.contrib.auth.models import User from myapps.serializers import UserSerializer from rest_framework import viewsets from rest_framework.response import Response class UserViewSet(viewsets.ViewSet): """ A simple ViewSet for listing or retrieving users. """ def list(self, request): queryset = User.objects.all() serializer = UserSerializer(queryset, many=True) return Response(serializer.data) def retrieve(self, request, pk=None): queryset = User.objects.all() user = get_object_or_404(queryset, pk=pk) serializer = UserSerializer(user) return Response(serializer.data)
3. 视图集功能实现及路由映射
视图集的路由映射不是之前的直接 as_view,还要采取对应请求进行映射
# urls.py path('userlist/', UserViewSet.as_view({'get': 'list'})), path('userdetail/', UserViewSet.as_view({'get': 'retrieve'})
ViewSet视图集类不再实现get、post等方法,而是实现动作 action 如 list、createl 等。使用视图集ViewSet,可以将一系列逻朝相关的动作放到一个类中:
- list() 提供一组数据
- retrieve() 提供单个数据
- create() 创建数据
- update() 保存数据
- destory() 删除数据
二、ModelViewSet
1. 混入类的视图集概念
在 ModelViewSet 类中继承了 GenericAPIView和各种混入类,在包括用于各种动作实现方式中,各种混入类的行为混合,包含了 .list、.retrieve、.create、.update、.partial_update、和 .destroy 等方法,继承了 ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestroyModelMixin,需要至少提供 queryset 和 serializer_class 属性
2. ModelViewSet视图集功能及路由映射
from rest_framework.viewsets import ModelViewSet class BookModelViewSet(ModelViewSet): queryset = Book.objects.all() lookup_field = 'pk' lookup_url_kwarg = 'pk' serializer_class = BookSer
这样具备全部混入类的视图类,只要提供对应数据属性即可完成功能
路由设置:
path('modelviewset/',BookModelViewSet.as_view( {'get':'list','post':'create'} )), path('modelviewset/<int:pk>/',BookModelViewSet.as_view( {'get':'retrieve','put':'update','delete':'destroy'} )),
3. 视图集自定义功能及路由映射
视图集自定义功能:
from rest_framework.decorators import action 视图集中,通过自定义请求方式,定义方法: @action(methods=['get'],detail=True) def getList(self,request,pk): ... return ... 以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。 action装饰器可以接收两个参数: methods: 声明该action对应的请求方式,列表传递 detail:声明该action的路径是否与单一资源对应 xxx/<pk>/action方法名/ True 表示路径格式是`xxx/<pk>/action方法名/` False 表示路径格式是`xxx/action方法名/
视图集中附加action的声明
- 在视图集中,如果想要让
Router
自动生成我们自定义动作的路由信息,需要使用rest_framework.decorators.action
装饰器- 以
action
装饰器装饰的方法名会作为action动作名
,与list
、retrieve
等同- action装饰器可以接收三个参数:
methods
: 声明该action对应的请求方式,列表detail
: 声明该action的路径是否与单一资源对应,True:单个数据操作,False:多个数据操作url_path
:声明该action的路由尾缀
# views.py class StudentsModelView(ModelViewSet): queryset = Students.objects serializer_class = StudentSerializers @action(methods=['get'], detail=False, url_path='login') def login(self, request): """登录""" return Response({'message': '成功!!'})
路由文件如下:
from rest_framework.routers import DefaultRouter from . import views # 实例化路由类 router = DefaultRouter() # 注册视图集 router.register('students', views.StudentsModelView) # 将生成的路由集添加到urlpatterns中 urlpatterns = [] urlpatterns += router.urls
访问方式如下:
http://127.0.0.1:8000/app/students/login/
三、DRF路由映射
对于视图集ViewSet,我们除了可以自己 手动指明请求方式与动作action之间的对应关系 外,还可以 使用drf所提供的路由功能Routers 来帮助我们快速实现路由信息,更加的方便快捷
Routers主要分如下两种:
- DefaultRouter
- SimpleRouter
1. DefaultRouter路由生成
在Django REST framework(DRF)中,
DefaultRouter
是routers
模块提供的一个类,它用于自动为你的应用中的视图集(ViewSets)生成URL模式。使用DefaultRouter
可以极大地简化URL配置的复杂性,特别是当你的应用包含多个与资源相关的视图集时。
DefaultRouter
为每个视图集自动生成以下URL模式:
- 列表视图(list view):返回资源对象列表
- 详情视图(detail view):返回单个资源对象
- 创建视图(create view):创建新的资源对象
- 更新视图(update view):更新现有的资源对象
- 删除视图(delete view):删除资源对象
比如我们编写一个视图集,具备有全部功能,采用ModelViewSet
#views.py class BookModelViewSet(ModelViewSet): serializer_class = BookSerializer queryset = Book.objects.all()
- 注册路由
#urls.py from rest_framework import routers # 1.实例化路由对象 router = routers.DefaultRouter() # 2.注册生成路由 router.register('book', BookModelViewSet) # 3.添加路由 urlpatterns += router.urls
- 此时生成的路由
app/ ^actions/$ [name='studentmodel-list'] app/ ^actions\.(?P<format>[a-z0-9]+)/?$ [name='studentmodel-list'] app/ ^actions/(?P<id>[^/.]+)/$ [name='studentmodel-detail'] app/ ^actions/(?P<id>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='studentmodel-detail'] app/ [name='api-root'] app/ <drf_format_suffix:format> [name='api-root']
- 我们看到中间还多了一些路由,是带有format正则匹配的,这些是用来获取纯粹json格式数据
app/ ^actions\.(?P<format>[a-z0-9]+)/?$ [name='studentmodel-list'] app/ ^actions/(?P<id>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='studentmodel-detail'] app/ <drf_format_suffix:format> [name='api-root']
- 比如直接通过浏览器访问接口地址,默认会返回DRF所提供的页面,但是此时数据被解析成了text/html格式,如果希望得到纯粹的json格式,那么可以利用上面DefaultRouter路由生成的新路由,直接访问如下连接,看到的就是直接的json格式返回,而不是html标签格式
http://127.0.0.1:8000/app/actions.json #app/ ^actions\.(?P<format>[a-z0-9]+)/?$ [name='studentmodel-list']
- 注意,除了使用urlpatterns进行路由拼接,还可使用include进行路由分发也是可以的
path('', include(router.urls)),
2. SimpleRouter路由生成
在Django REST framework(DRF)中,
SimpleRouter
是routers
模块提供的一个类,用于为视图集生成路由URL,它是一个简单的路由,为视图集生成标准的URL模式,且不会添加额外的API根视图等,与DefaultRouter
相比,它更加简洁,只关注于基本的URL生成功能。
- 注册路由
from rest_framework import routers # 1.实例化路由对象 router = routers.SimpleRouter() # 2.注册生成路由 router.register('actions', IndexActinosView, basename='actions') # 3.添加路由 urlpatterns += router.urls
- 创建好的路由如下所示,虽然你只看到两条路由
但其实每一条路由后面都映射了可以保留的请求方式及action的映射
app/ ^actions/$ [name='studentmodel-list'] #包含:获取列表get,创建一条信息post app/ ^actions/(?P<id>[^/.]+)/$ [name='studentmodel-detail'] #包含:获取一条信息get,更新一条信息put,删除一条信息delete
- 路由对象register方法参数介绍
# 1.实例化路由对象 router = routers.SimpleRouter() # 2.注册生成路由 router.register('路由命名', 视图集, basename='路由名称前缀')
3. 两种路由生成方式区别及根路由是什么
SimpleRouter
:最基本的路由映射方式,只会将视图集具备的混入类功能进行路由的生成DefaultRouter
:对比与SimpleRouter更加高级,包含有drf根页面的路由,不只是视图集所包含的视图部分根路由
是一个特殊的路由,用于处理对网站根目录的请求,并通常列出所有可用的API端点。
根路由定义:
根路由 通常是一个特殊的路由,它位于路由系统的最顶层,用于处理对网站根目录(如/)的请求。在Django REST framework中,使用DefaultRouter时,会自动生成一个根路由,该路由会列出所有可用的API端点。这使得开发者能够方便地查看和理解API的结构。