Django REST framework视图集与路由详解:深入理解ViewSet、ModelViewSet与路由映射器

系列文章目录


文章目录

  • 系列文章目录
  • 前言
  • 一、ViewSet
    • [1. 视图集是什么](#1. 视图集是什么)
    • [2. action 是什么](#2. action 是什么)
    • [3. 视图集功能实现及路由映射](#3. 视图集功能实现及路由映射)
  • 二、ModelViewSet
    • [1. 混入类的视图集概念](#1. 混入类的视图集概念)
    • [2. ModelViewSet视图集功能及路由映射](#2. ModelViewSet视图集功能及路由映射)
    • [3. 视图集自定义功能及路由映射](#3. 视图集自定义功能及路由映射)
  • 三、DRF路由映射
    • [1. DefaultRouter路由生成](#1. DefaultRouter路由生成)
    • [2. SimpleRouter路由生成](#2. SimpleRouter路由生成)
    • [3. 两种路由生成方式区别及根路由是什么](#3. 两种路由生成方式区别及根路由是什么)

前言

在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 是什么

视图集类不再实现 getpost 等方法,而是实现动作 actionlistcreate 等,视图集 只在使用 as_view 方法的时候,才会将 action 动作与具体请求方式对应上
例如,下面编写的最基本的视图集:

python 复制代码
# 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,还要采取对应请求进行映射

python 复制代码
# 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 等方法,继承了 ListModelMixinRetrieveModelMixinCreateModelMixinUpdateModelMixinDestroyModelMixin ,需要至少提供 querysetserializer_class 属性

2. ModelViewSet视图集功能及路由映射

python 复制代码
from rest_framework.viewsets import ModelViewSet
class BookModelViewSet(ModelViewSet):
   queryset = Book.objects.all()
   lookup_field = 'pk'
   lookup_url_kwarg = 'pk'
   serializer_class = BookSer

这样具备全部混入类的视图类,只要提供对应数据属性即可完成功能
路由设置:

python 复制代码
path('modelviewset/',BookModelViewSet.as_view(
    {'get':'list','post':'create'}
)),
path('modelviewset/<int:pk>/',BookModelViewSet.as_view(
    {'get':'retrieve','put':'update','delete':'destroy'}
)),

3. 视图集自定义功能及路由映射

视图集自定义功能:

python 复制代码
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动作名,与listretrieve等同
  • action装饰器可以接收三个参数:
    • methods: 声明该action对应的请求方式,列表
    • detail: 声明该action的路径是否与单一资源对应,True:单个数据操作,False:多个数据操作
    • url_path:声明该action的路由尾缀
python 复制代码
# 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': '成功!!'})

路由文件如下:

python 复制代码
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)中,DefaultRouterrouters 模块提供的一个类,它用于自动为你的应用中的视图集(ViewSets)生成URL模式。使用 DefaultRouter 可以极大地简化URL配置的复杂性,特别是当你的应用包含多个与资源相关的视图集时。
DefaultRouter 为每个视图集自动生成以下URL模式:

  • 列表视图(list view):返回资源对象列表
  • 详情视图(detail view):返回单个资源对象
  • 创建视图(create view):创建新的资源对象
  • 更新视图(update view):更新现有的资源对象
  • 删除视图(delete view):删除资源对象

比如我们编写一个视图集,具备有全部功能,采用ModelViewSet

python 复制代码
#views.py
class BookModelViewSet(ModelViewSet):
    serializer_class = BookSerializer
    queryset = Book.objects.all()
  • 注册路由
python 复制代码
#urls.py
from rest_framework import routers
# 1.实例化路由对象
router = routers.DefaultRouter() 
# 2.注册生成路由
router.register('book', BookModelViewSet)
# 3.添加路由
urlpatterns += router.urls  
  • 此时生成的路由
python 复制代码
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格式数据
python 复制代码
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标签格式
python 复制代码
http://127.0.0.1:8000/app/actions.json
#app/ ^actions\.(?P<format>[a-z0-9]+)/?$ [name='studentmodel-list']
  • 注意,除了使用urlpatterns进行路由拼接,还可使用include进行路由分发也是可以的
python 复制代码
path('', include(router.urls)),

2. SimpleRouter路由生成

在Django REST framework(DRF)中,SimpleRouterrouters 模块提供的一个类,用于为视图集生成路由URL,它是一个简单的路由,为视图集生成标准的URL模式,且不会添加额外的API根视图等,与 DefaultRouter 相比,它更加简洁,只关注于基本的URL生成功能。

  • 注册路由
python 复制代码
from rest_framework import routers
# 1.实例化路由对象
router = routers.SimpleRouter()
# 2.注册生成路由
router.register('actions', IndexActinosView, basename='actions')
# 3.添加路由
urlpatterns += router.urls  
  • 创建好的路由如下所示,虽然你只看到两条路由
    但其实每一条路由后面都映射了可以保留的请求方式及action的映射
python 复制代码
app/ ^actions/$ [name='studentmodel-list']
#包含:获取列表get,创建一条信息post
app/ ^actions/(?P<id>[^/.]+)/$ [name='studentmodel-detail']
#包含:获取一条信息get,更新一条信息put,删除一条信息delete
  • 路由对象register方法参数介绍
python 复制代码
# 1.实例化路由对象
router = routers.SimpleRouter()
# 2.注册生成路由
router.register('路由命名', 视图集, basename='路由名称前缀')

3. 两种路由生成方式区别及根路由是什么

  • SimpleRouter:最基本的路由映射方式,只会将视图集具备的混入类功能进行路由的生成
  • DefaultRouter:对比与SimpleRouter 更加高级,包含有drf根页面的路由,不只是视图集所包含的视图部分
  • 根路由是一个特殊的路由,用于处理对网站根目录的请求,并通常列出所有可用的API端点。

根路由定义:
根路由 通常是一个特殊的路由,它位于路由系统的最顶层,用于处理对网站根目录(如/)的请求。在Django REST framework中,使用DefaultRouter时,会自动生成一个根路由,该路由会列出所有可用的API端点。这使得开发者能够方便地查看和理解API的结构。


相关推荐
满心欢喜love14 分钟前
Python爬虫康复训练——笔趣阁《神魂至尊》
开发语言·爬虫·python
阿福不是狗26 分钟前
PyQt5之理解和使用Python中的qasync:连接Qt和asyncio的桥梁
数据库·python·qt
wxin_VXbishe32 分钟前
springboot城市菜园共享系统-计算机毕业设计源码00524
java·hadoop·spring boot·python·spring·django·php
sssugarr41 分钟前
从0开始学习pyspark--pyspark的数据分析方式[第2节]
python·数据挖掘·数据分析·spark
测试界清流1 小时前
Python自动化测试框架unittest与pytest的区别
开发语言·python·pytest
程序无涯海1 小时前
Python爬虫教程第0篇-写在前面
开发语言·爬虫·python·教程·python爬虫
raykingl1 小时前
154. 寻找旋转排序数组中的最小值 II(困难)
java·python·算法·二分查找
raykingl1 小时前
69. x 的平方根(简单)
java·python·算法·二分查找
铅笔楼1 小时前
#笔记# 写给自己用的小爬虫
经验分享·笔记·python·旅游
Papicatch1 小时前
【人工智能】--强化学习(2.0)
人工智能·python·动态规划·马尔科夫决策过程·actor-critic算法