Django REST Framework(DRF)框架之视图集ViewSet与路由Router

news2024/11/16 16:36:09

DRF框架之视图集ViewSet

  • 视图集ViewSet与路由Router
    • 视图集ViewSet
    • 路由Router
    • 视图集和路由的基本使用
  • 视图集ViewSet的使用
    • ViewSet
    • GenericViewSet
    • ModelViewSet
    • ReadOnlyModelViewSet
    • 视图集添加其他方法
    • 视图集对象action属性
  • 路由Router的使用
    • SimpleRouter
    • DefaultRouter
    • 基本使用
    • 自定义方法生成路由

视图集ViewSet与路由Router

视图集ViewSet

在DRF中,视图集(Viewsets)是一种特殊的视图类,它将多个视图组合在一起,方便进行管理和维护,并提供通用的CRUD操作。

视图集可以分为两种类型:基于Model的视图集和基于普通类的视图集。基于Model的视图集允许快速创建一个RESTful API,它可以执行标准的CRUD操作。而基于普通类的视图集则允许更加灵活地定义自己的API逻辑。

视图集主要有以下几种:

1. ViewSet:扩展APIView,具有更加灵活的操作方式

2. GenericViewSet:可以自定义操作,需要手动指定queryset和serializer_class属性

3. ModelViewSet: 处理与模型相关的操作(list, create, retrieve, update, partial_update, destroy)

4. ReadOnlyModelViewSet:只读操作,相当于ModelViewSet中的list和retrieve方法

路由Router

在Django中,路由用于将请求映射到相应的视图函数上。而在DRF中,路由则用于将请求映射到视图集上。

在DRF中,视图集通常会与路由器(Router)一起使用,以便自动注册URL,并将请求分配给相应的视图集方法。

Routers提供了一种简单的方式来自动生成URL路由,将HTTP请求映射到相应的视图函数上。使用Routers可以大大减少代码量,降低开发难度。

DRF提供了两种路由方式:

1. SimpleRouter: 适用于基本的CRUD操作

2. DefaultRouter:更加灵活,可以支持自定义操作

视图集和路由的基本使用

定义一个模型类

from django.db import models

class User(models.Model):
    name = models.CharField(max_length=6, unique=True, verbose_name='姓名')
    age = models.IntegerField(default=0, verbose_name='年龄')

    class Meta:
        db_table = 'tb_user'
        verbose_name = '用户'
        verbose_name_plural = verbose_name
        
    def __str__(self):
        return "name:%s age:%s" % (self.name, self.age)

定义一个序列化器类

from rest_framework import serializers

from user.models import User

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'

定义一个UserViewSet视图集

from rest_framework import viewsets

from user.models import User
from user.utils import UserSerializer


class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

将视图集注册到SimpleRouter路由中。接着将路由的urls属性添加到Django的urlpatterns列表中即可。

from user import views

urlpatterns = [

]

# 创建Router对象
from rest_framework.routers import SimpleRouter

router = SimpleRouter()
# 注册视图集
router.register('user', views.UserViewSet, basename='users')
# 打印生成的url配置项
for url in router.urls:
    print(url)

# 将生成的路由配置项添加到urlpatterns列表中
urlpatterns = router.urls

将会自动生成两个Router配置项

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

因此,使用DRF的视图集和路由可以快速地构建出完整且灵活的API。

视图集ViewSet的使用

ViewSet

ViewSet继承自APIView与ViewSetMixin,作用与APIView基本类似,提供了身份认证、权限校验、流量管理等。

视图集中的处理方法不再对应请求方式(get、post等)命名,而是以对应的操作(action)命名。

list:提供一组数据
retrieve:提供单个数据
create:创建数据
update:保存数据
destory:删除数据
class UserViewSet(viewsets.ViewSet):
    def list(self, request):
        users = User.objects.all()
        serializer = UserSerializer(users, many=True)
        return Response(serializer.data)

    def create(self, request):
        serializer = UserSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    def retrieve(self, request, pk):
        try:
            user = User.objects.get(id=pk)
        except User.DoesNotExist:
            raise Http404

        serializer = UserSerializer(user)
        return Response(serializer.data)

    def update(self, request, pk):
        try:
            user = User.objects.get(id=pk)
        except User.DoesNotExist:
            raise Http404

        serializer = UserSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

    def destroy(self, request, pk):
        try:
            user = User.objects.get(id=pk)
        except User.DoesNotExist:
            raise Http404

        user.delete()
        return Response(status=status.HTTP_204_NOT_CONNECTED)

在进行URL配置时,需要明确指明某个请求方式请求某个URL地址时,对应的是视图集中的哪个处理函数。

urlpatterns = [
    re_path(r'^test/$', views.TestView.as_view({
        'get': 'list',
        'post': 'create'
    })),
    re_path(r'^test/(?P<pk>\d+)/$', views.TestView.as_view({
        'get': 'retrieve',
        'put': 'update',
        'delete': 'destroy'
    }))
]

GenericViewSet

GenericViewSet继承自GenericAPIView与ViewSetMixin,可以直接搭配Mixin扩展类使用。

from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet


class TestView(mixins.ListModelMixin,
               mixins.CreateModelMixin,
               mixins.RetrieveModelMixin,
               mixins.UpdateModelMixin,
               mixins.DestroyModelMixin,
               GenericViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
urlpatterns = [
    re_path(r'^test/$', views.TestView.as_view({
        'get': 'list',
        'post': 'create'
    })),
    re_path(r'^test/(?P<pk>\d+)/$', views.TestView.as_view({
        'get': 'retrieve',
        'put': 'update',
        'delete': 'destroy'
    }))
]

ModelViewSet

ModelViewSet继承自GenericViewSet,同时包括ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。

from rest_framework import mixins
from rest_framework.viewsets import ModelViewSet

class BookInfoViewSet(ModelViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer
urlpatterns = [
    re_path(r'^test/$', views.TestView.as_view({
        'get': 'list',
        'post': 'create'
    })),
    re_path(r'^test/(?P<pk>\d+)/$', views.TestView.as_view({
        'get': 'retrieve',
        'put': 'update',
        'delete': 'destroy'
    }))
]

ReadOnlyModelViewSet

ReadOnlyModelViewSet继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin。

from rest_framework.viewsets import ReadOnlyModelViewSet

class TestView(ReadOnlyModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
urlpatterns = [
    re_path(r'^test/$', views.TestView.as_view({
        'get': 'list',
    })),
    re_path(r'^test/(?P<pk>\d+)/$', views.TestView.as_view({
        'get': 'retrieve',
    }))
]

视图集添加其他方法

在视图集中,除了默认的action处理方法之外,还可以添加额外的其他处理方法。

class TestView(ViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def other(self, request, pk):
        user = User.objects.get(id=pk)
        serializer = UserSerializer(user)
        return Response(serializer.data)
    re_path(r'^test/$', views.TestView.as_view({
        'get': 'list',
    })),
    re_path(r'^test/(?P<pk>\d+)/$', views.TestView.as_view({
        'get': 'retrieve',
    })),
    re_path(r'^test/other/(?P<pk>\d+)/$', views.TestView.as_view({
        'get': 'other'
    }))

Get http://127.0.0.1:8000/test/other/1/

视图集对象action属性

在视图集中,可以通过视图集对象.action获取所有执行action的操作。

应用场景:重写get_serializer_class和get_queryset,根据不同的action操作返回不同的序列化器类和不同的查询集。

def get_serializer_class(self):
    if self.action == 'list':
        return 'list操作所使用的序列化器类'
    else:
        return '其他操作所使用的序列化器类'

def get_queryset(self):
    if self.action == 'list':
        return 'list操作所使用的查询集'
    else:
        return '其他操作所使用的查询集'
class TestView(ViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def other(self, request, pk):
        user = self.get_object(pk)
        serializer = self.get_serializer(user)
        return Response(serializer.data)

    def get_serializer(self, user):
        if self.action == 'other':
            return UserSerializer(user)
        else:
            return self.serializer_classa

    def get_object(self, pk):
        if self.action == 'other':
            return User.objects.get(id=pk)
        else:
            return self.queryset

路由Router的使用

对于视图集ViewSet,除了可以手动进行URL配置指明请求方式与action处理函数之间的对应关系外,还可以使用路由Router来自动生成路由信息。

SimpleRouter

SimpleRouter为每一条url添加一个斜杠后缀,可以在初始化的时候提供 trailing_slash 参数,并设置为 False

router = SimpleRouter(trailing_slash=False)

SimpleRouter生成URL的方式
在这里插入图片描述

DefaultRouter

DefaultRouter会生成一个根路径/的配置项
		
DefaultRouter生成的每个配置项后都可以跟上.json,直接返回json数据

DefaultRouter生成URL的方式

在这里插入图片描述

基本使用

创建Router对象,并注册视图集。

from rest_framework.routers import SimpleRouter, DefaultRouter

router = SimpleRouter() 或 DefaultRouter()

注册视图集

# prefix:该视图集所有处理函数url地址的统一前缀
# viewset:视图集
# base_name:该视图集所有处理函数路由name的统一前缀
router.register(prefix, viewset, base_name)

添加路由数据,将生成的路由配置项添加到urlpatterns列表中

urlpatterns = [
	
]

# 通过router.urls可以获取路由Router生成的url配置项列表。
urlpatterns += router.urls

完整使用如下:

from user import views

urlpatterns = [

]

# 创建Router对象
from rest_framework.routers import SimpleRouter

router = SimpleRouter()
# 注册视图集
router.register('user', views.UserViewSet, basename='users')
# 打印生成的url配置项
for url in router.urls:
    print(url)

# 将生成的路由配置项添加到urlpatterns列表中
urlpatterns = router.urls

将会生成两个Router配置项

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

可以指定提取参数的正则表达式,在视图集中设置lookup_value_regex指定。

class UserViewSet(ModelViewSet):
    # 指定路由Router生成url配置项时,从路径中提取参数的正则表达式
    lookup_value_regex = '\d+'
    queryset = User.objects.all()
    serializer_class = UserSerializer
<URLPattern '^user/$' [name='users-list']>
<URLPattern '^user/(?P<pk>\d+)/$' [name='users-detail']>

settings.py设置使用JSON渲染器

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
    ],
}

访问测试

http://127.0.0.1:8000/user/user/

http://127.0.0.1:8000/user/user/1

自定义方法生成路由

在视图集中,如果想要让路由Router自动生成视图集中额外添加的处理方法的url配置项,需要给额外的处理方法添加rest_framework.decorators.action装饰器。

action装饰器可以接收两个参数:

methods:表明该处理方法对应的请求方式,列表传递

detail:表明生成url配置项时,是否需要从路径中提取pk数据
	True:生成url配置项时,需要从url地址中提取pk参数
	False:生成url配置项时,不需要从url地址中提取pk参数
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response

from user.models import User
from user.utils import UserSerializer


class UserViewSet(viewsets.ModelViewSet):
    lookup_value_regex = '\d+'

    @action(methods=["get"], detail=False, )
    def test1(self, request):
        users = User.objects.all()
        print(users)
        serializer = UserSerializer(users, many=True)
        return Response(serializer.data)

    @action(methods=["get"], detail=True)
    def test2(self, request, pk):
        users = User.objects.get(id=pk)
        serializer = UserSerializer(users)
        return Response(serializer.data)

test1函数

使用 @action 装饰器将方法添加到视图集中,并将其映射到名为/test1/的路由。该方法使用 GET 请求返回所有用户的数据,并使用 UserSerializer 序列化响应数据。

test2函数

使用 @action 装饰器将方法添加到视图集中,并将其映射到名为 /users/<pk>/test2/ 的路由。该方法使用 GET 请求返回具有给定主键值的用户的数据,并使用 UserSerializer 序列化响应数据。

参数提取:

lookup_value_regex 属性设置为 \d+,这表示主键值必须是数字。

<URLPattern '^user/$' [name='users-list']>
<URLPattern '^user/test1/$' [name='users-test1']>
<URLPattern '^user/(?P<pk>\d+)/$' [name='users-detail']>
<URLPattern '^user/(?P<pk>\d+)/test2/$' [name='users-test2']>

访问测试

http://127.0.0.1:8000/user/user/test1/

http://127.0.0.1:8000/user/user/1/test2/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/439059.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DELL R730 主板坏了,Raid5硬盘移到同型号服务器备忘

1、开机时按ctrlr进入raid设置页面 2、进入raid设置页面后可以看到没有找到虚拟磁盘&#xff0c;我们按F2打开操作菜单 3、选择菜单Foreign Config -> Import &#xff0c;选择Yes开始导入硬盘中的raid配置 4、导入成功的话就可以看到虚拟盘了 5、按Esc退出 6、按ctrlaltd…

为什么网络安全缺口很大,招聘却很少?

2020年我国网络空间安全人才数量缺口超过了140万&#xff0c;就业人数却只有10多万&#xff0c;缺口高达了93%。这里就有人会问了&#xff1a; 1、网络安全行业为什么这么缺人&#xff1f; 2、明明人才那么稀缺&#xff0c;为什么招聘时招安全的人员却没有那么多呢&#xff1…

迅为RK3568核心板车载中控AVM一体机应用

RK3568M车载中控&AVM一体机方案搭载4核A55 CPU&#xff0c;G52-2EE GPU架构&#xff0c;1Tops算力NPU&#xff0c;支持1路4K 60fps或8路1080P 30fps的多格式解码和高达1080P 100fps的H.265编码&#xff0c;具备双千兆GMAC、三路CAN以及USB3.0/SATA3.0/PCIE3.0等丰富接口&am…

Windows安装mysql详细步骤

目录 1 【确认本地是否安装mysql】 2【下载mysql安装包】 3【添加配置文件并安装mysql】 4【修改mysql密码】 5【配置环境变量】 windows 只安装mysql服务的操作 1 【确认本地是否安装mysql】 &#xff08;1&#xff09;按【winr】快捷键打开运行&#xff1b; &#xff…

java基于蚁群算法路由选择可视化动态模拟

蚁群算法是一种新生的算法&#xff0c;具有很强的通用性。从提出到现在&#xff0c;仅短短10余年的时间&#xff0c;但是在离散型组合优化问题中。表现很突出&#xff0c;所以一起人们的关注。目前蚁群算法的研究者主要集中在比利时、意大利、德国等国家&#xff0c;美国和日本…

Muduo 异步log的实现

1. logging 日志(logging) 有两个意思: 诊断日志: 即是我们日常debug 使用的文本文件记录trace。常用的log 有log4j, logback, log4cpp, ezlogger等常用的日志库。交易日志: 即是数据库的write-ahead log&#xff0c; 文件系统的journaling 等&#xff0c; 用于记录状态的变更…

软考 - IP地址与网络划分

一.IP组成 1.1 首个八位字节规则 1.2 地址掩码 IP地址掩码 标准地址掩码 A类&#xff1a;255.0.0.0 前1个字节是网络号 后3个字节是主机号 B类&#xff1a;255.255.0.0 前2个字节是网络号 后2个字节是主机号 C类&#xff1b;255.255.255.0 前3个字节是网络号 后1个字节是主机号…

nssctf web 入门(5)

这里通过nssctf的题单web安全入门来写&#xff0c;会按照题单详细解释每题。题单在NSSCTF中。 想入门ctfweb的可以看这个系列&#xff0c;之后会一直出这个题单的解析&#xff0c;题目一共有28题&#xff0c;打算写10篇。 目录 [鹤城杯 2021]EasyP [SWPUCTF 2021 新生赛]eas…

VR全景--720全景 助力行业数字化新模式

引言 720全景就是视角超过人的正常视角的图像&#xff0c;而我们这里说的全景特指水平360度&#xff0c;上下360度全能观看的&#xff0c;能看到“天、地”的全景。全景实际上只是一种对周围景象以某种几何关系进行映射生成的平面图片&#xff0c;只有通过全景播放器的矫正处理…

电力监控系统高扩展性的设计思路与方法

安科瑞 徐浩竣 江苏安科瑞电器制造有限公司 zx acrelxhj 电力监控软件的可扩展性设计 2023-04-19 14:00AcreXHJ 安科瑞 徐浩竣 江苏安科瑞电器制造有限公司 zx acrelxhj 摘要&#xff1a;本文根据安科瑞电力监控系统软件的设计过程&#xff0c;论述了电力监控系统高扩展…

JS 正则表达式(正则匹配RegExp)

JavaScript实现对象深拷贝的方法&#xff08;5种&#xff09; 知识回调&#xff08;不懂就看这儿&#xff01;&#xff09;场景复现核心干货举例引入关于RegExp对象语法修饰符——区分大小写和全局匹配方括号——查找某个范围内的字符元字符——拥有特殊含义的字符量词RegExp对…

4.Hadoop三件套(1)

如果说HDFS是存储,则Yarn就是cpu和内存,mapreduce就是程序。 1.HDFS文件块大小 HDFS中的文件在物理.上是分块存储(Block) ,block默认保存3份块的大小可以通过配置参数(dfs blocksize)来规定,默认大小在Hadoop2 .x版本中是128M,老版本中是64M。 解释:块的大小:10ms*100*…

代码随想录算法训练营第48天 | 动态规划 LeetCode198.打家劫舍,213.打家劫舍II,337.打家劫舍 III

代码随想录算法训练营第48天 | 动态规划 LeetCode198.打家劫舍&#xff0c;213.打家劫舍II&#xff0c;337.打家劫舍 III 198.打家劫舍 第一遍读题思考 dp[i]代表打劫到第i家的时候抢到的最多的钱数。 那么递推公式就跟dp[i-1] and dp[i-2]有关&#xff0c;如果抢i-1家的&am…

【梦回stm32】-寄存器篇-跑马灯代码研读-总结

前言&#xff1a;学就要学懂&#xff0c;别以为做出来就行&#xff0c;要弄懂通路&#xff0c;思路要清楚-谨记 1.先讲讲背景&#xff0c;此次需要研究的是stm32的跑马灯代码&#xff0c;下图是个本实验用的正点原子的代码目录 1&#xff09;HARDWARE-》LED 2&#xff09;SYS…

【COMP282 LEC 1-2】

LEC 1 Introduction to c Header file : 1. 不用写 " .h " Function : 数据类型有string了&#xff0c;就像java&#xff0c;需要#include<string> Output system : Explain by example: std::cout << hello << " is of length "…

电脑IP地址查询,3个实用方法!

案例&#xff1a;电脑IP地址怎么查询 【请问有没有朋友知道电脑IP地址怎么查询呀&#xff1f;想看看我的IP地址却不知道该怎么查询&#xff0c;哪位友友可以帮帮我&#xff01;】 在互联网世界中&#xff0c;IP地址是一种用于标识设备&#xff08;如电脑、手机等&#xff09;…

在OLED上显示各种各样的数据(文字、字母、图片)

今天来说一说OLED&#xff0c;也同时记录一下成果。 在学习OLED之前需要知道IIC协议&#xff0c;不了解的可以看&#xff08;IIC协议相关_dxdlnu的博客-CSDN博客&#xff09; 什么是OLED? OLED_百度百科 (baidu.com) 一.OLED写入指令和数据 因为OLED是有写入指令/数据的操作…

camunda工作流引擎多租户架构

Camunda支持多租户的方式有两种&#xff1a;共享引擎和多引擎。 1、共享引擎 在共享引擎的模式下&#xff0c;多个租户共享同一个Camunda引擎。每个租户的数据被存储在引擎中的不同表中&#xff0c;而引擎的配置和部署是共享的。可以通过以下方式实现共享引擎&#xff1a; &…

OpenAI-ChatGPT最新官方接口《微调ChatGPT模型》全网最详细中英文实用指南和教程,助你零基础快速轻松掌握全新技术(四)(附源码)

微调ChatGPT模型 前言Introduction 导言What models can be fine-tuned? 哪些模型可以微调&#xff1f;Installation 安装Prepare training data 准备训练数据CLI data preparation tool CLI数据准备工具Create a fine-tuned model 创建微调模型Use a fine-tuned model 使用微…

​HTTP和TCP协议的队头阻塞​

队头阻塞&#xff08;Head-of-line blocking&#xff09;其实有两种&#xff0c;一种是 TCP 队头阻塞&#xff0c;另一种是 HTTP 队头阻塞&#xff0c;而这两者之前其实还存在一定的联系&#xff0c;毕竟 HTTP1/2 是建立在 TCP 协议之上的应用层协议&#xff0c;另外还有HTTP3对…