【django】Django REST Framework 构建 API:APIView 与 ViewSet
目录
1、APIView
2、ViewSet
3、APIVIew例子
3.1 模型定义
3.2 序列化器定义
3.3 使用视图
3.3.1 ProductListCreateAPIView 类
3.3.2 ProductRetrieveUpdateDestroyAPIView 类
3.4 配置url
3.5 测试
3.5.1 查询全部
3.5.2 添加产品
3.5.3 查询单个产品
3.5.4 修改单个产品
3.5.5 删除单个产品
4、VIEWSet例子
4.1 模型定义
4.2 序列化器定义
4.3 使用视图
4.4 配置url
4.5 测试
4.5.1 查询全部
4.5.2 添加产品
4.5.3 查询单个产品
4.5.4 修改单个产品
4.5.5 删除单个产品
5、总结
5.1 APIView
5.2 ViewSet
前言:针对drf框架对比APIView与ViewSet的优缺点与示例,建议先看上一篇【django】Django REST Framework 序列化与反序列化详解-CSDN博客
1、APIView
APIView 类是 DRF 中最基本的类视图。它继承自 Django 的 View 类,并添加了对请求解析、认证、权限检查等的支持。使用 APIView 可以让你更细粒度地控制每个 HTTP 方法的行为。
优点
细粒度控制:你可以完全控制每个 HTTP 方法的行为。
灵活性:适用于需要复杂逻辑的场景。
缺点
冗余代码:对于简单的 CRUD 操作,可能会导致代码重复。
维护成本:随着功能增加,代码量会变得庞大且难以维护。
2、ViewSet
ViewSet 提供了一种更简洁的方式来处理常见的 CRUD 操作。它允许你将多个相关的操作组合在一起,从而减少代码冗余并提高可维护性。
优点
简洁:自动处理常见的 CRUD 操作,减少了代码量。
一致性:提供了一致的 URL 结构和行为。
易于扩展:可以通过覆盖方法轻松扩展功能。
缺点
抽象程度高:对于非常复杂的业务逻辑,可能需要更多的定制。
学习曲线:初学者可能需要时间来理解 ViewSet 的工作原理。
3、APIVIew例子
3.1 模型定义
假设我们有一个简单的库存管理系统,包含以下三张表:Category(类别)、Product(产品)和 Supplier(供应商)。我们将基于这些表来实现类似于之前 Book 表的 CRUD 操作
# newapp/models.py
from django.db import modelsclass Category(models.Model):name = models.CharField(max_length=100)description = models.TextField(blank=True, null=True)def __str__(self):return self.nameclass Supplier(models.Model):name = models.CharField(max_length=100)contact_person = models.CharField(max_length=100, blank=True, null=True)email = models.EmailField(blank=True, null=True)phone = models.CharField(max_length=20, blank=True, null=True)def __str__(self):return self.nameclass Product(models.Model):name = models.CharField(max_length=255)category = models.ForeignKey(Category, on_delete=models.CASCADE)supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE)price = models.DecimalField(max_digits=10, decimal_places=2)stock_quantity = models.IntegerField()description = models.TextField(blank=True, null=True)def __str__(self):return self.name
3.2 序列化器定义
# newapp/serializers.py
from rest_framework import serializers
from .models import Category, Product, Supplierclass CategorySerializer(serializers.ModelSerializer):class Meta:model = Categoryfields = ['id', 'name', 'description']class SupplierSerializer(serializers.ModelSerializer):class Meta:model = Supplierfields = ['id', 'name', 'contact_person', 'email', 'phone']class ProductSerializer(serializers.ModelSerializer):# 用于写入的字段category_id = serializers.PrimaryKeyRelatedField(queryset=Category.objects.all(),source='category',write_only=True,required=True # 确保这个字段是必填的)supplier_id = serializers.PrimaryKeyRelatedField(queryset=Supplier.objects.all(),source='supplier',write_only=True,required=True # 确保这个字段是必填的)# 用于读取的嵌套字段category = CategorySerializer(read_only=True)supplier = SupplierSerializer(read_only=True)class Meta:model = Productfields = ['id', 'name', 'category_id', 'category', 'supplier_id', 'supplier','price', 'stock_quantity', 'description']def create(self, validated_data):category = validated_data.pop('category')supplier = validated_data.pop('supplier')product = Product.objects.create(category=category,supplier=supplier,**validated_data)return productdef update(self, instance, validated_data):if 'category' in validated_data:instance.category = validated_data.pop('category')if 'supplier' in validated_data:instance.supplier = validated_data.pop('supplier')for attr, value in validated_data.items():setattr(instance, attr, value)instance.save()return instancedef validate(self, data):if 'category' not in data or 'supplier' not in data:raise serializers.ValidationError("Both category_id and supplier_id are required.")return data
3.3 使用视图
我们定义两个基于 APIView 的视图类,分别处理产品的列表和创建操作,以及单个产品的获取、更新和删除操作。
3.3.1 ProductListCreateAPIView 类
# newapp/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Product
from .serializers import ProductSerializerclass ProductListCreateAPIView(APIView):def get(self, request):products = Product.objects.all()serializer = ProductSerializer(products, many=True)return Response(serializer.data)def post(self, request):serializer = ProductSerializer(data=request.data)if serializer.is_valid():serializer.save()return Response(serializer.data, status=status.HTTP_201_CREATED)return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
3.3.2 ProductRetrieveUpdateDestroyAPIView
类
class ProductRetrieveUpdateDestroyAPIView(APIView):def get_object(self, pk):try:return Product.objects.get(pk=pk)except Product.DoesNotExist:return Nonedef get(self, request, pk):product = self.get_object(pk)if not product:return Response(status=status.HTTP_404_NOT_FOUND)serializer = ProductSerializer(product)return Response(serializer.data)def put(self, request, pk):product = self.get_object(pk)if not product:return Response(status=status.HTTP_404_NOT_FOUND)serializer = ProductSerializer(product, data=request.data)if serializer.is_valid():serializer.save()return Response(serializer.data)return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)def delete(self, request, pk):product = self.get_object(pk)if not product:return Response(status=status.HTTP_404_NOT_FOUND)product.delete()return Response(status=status.HTTP_204_NO_CONTENT)
3.4 配置url
# newapp/urls.py
from django.urls import path
from .views import ProductListCreateAPIView, ProductRetrieveUpdateDestroyAPIViewurlpatterns = [path('products/', ProductListCreateAPIView.as_view(), name='product-list-create'),path('products/<int:pk>/', ProductRetrieveUpdateDestroyAPIView.as_view(), name='product-retrieve-update-destroy'),
]
3.5 测试
3.5.1 查询全部
http://127.0.0.1:8000/drf/products/
[{"id": 1,"name": "空调","category": {"id": 1,"name": "家电","description": ""},"supplier": {"id": 3,"name": "格力","contact_person": "董明珠","email": null,"phone": null},"price": "3459.00","stock_quantity": 100,"description": ""},{"id": 2,"name": "空调","category": {"id": 1,"name": "家电","description": ""},"supplier": {"id": 2,"name": "海信","contact_person": "贾少谦","email": null,"phone": null},"price": "2300.00","stock_quantity": 5,"description": ""},{"id": 3,"name": "电视","category": {"id": 1,"name": "家电","description": ""},"supplier": {"id": 1,"name": "TCL","contact_person": "彭攀","email": null,"phone": null},"price": "2500.00","stock_quantity": 5,"description": ""},{"id": 4,"name": "电视","category": {"id": 1,"name": "家电","description": ""},"supplier": {"id": 2,"name": "海信","contact_person": "贾少谦","email": null,"phone": null},"price": "2700.00","stock_quantity": 2,"description": ""},{"id": 5,"name": "热水器","category": {"id": 2,"name": "厨卫","description": ""},"supplier": {"id": 4,"name": "万家乐","contact_person": "罗潘","email": null,"phone": null},"price": "1600.00","stock_quantity": 5,"description": ""}
]
3.5.2 添加产品
http://127.0.0.1:8000/drf/products/
请求体
{"name": "电视","category_id": 1,"supplier_id": 5,"price": "2599.99","stock_quantity": 50,"description": "新增库存"
}
3.5.3 查询单个产品
http://127.0.0.1:8000/drf/products/8/
3.5.4 修改单个产品
http://127.0.0.1:8000/drf/products/8/
请求体
{"name": "电视333","category_id": 1,"supplier_id": 5,"price": "2599.99","stock_quantity": 1,"description": "修改库存"
}
3.5.5 删除单个产品
http://127.0.0.1:8000/drf/products/8/
4、VIEWSet例子
4.1 模型定义
模型不变,同上
4.2 序列化器定义
不变,同上
4.3 使用视图
# newapp/views.py
from rest_framework import viewsets
from .models import Category, Product, Supplier
from .serializers import CategorySerializer, ProductSerializer, SupplierSerializerclass CategoryViewSet(viewsets.ModelViewSet):queryset = Category.objects.all()serializer_class = CategorySerializerclass SupplierViewSet(viewsets.ModelViewSet):queryset = Supplier.objects.all()serializer_class = SupplierSerializerclass ProductViewSet(viewsets.ModelViewSet):queryset = Product.objects.all()serializer_class = ProductSerializer
4.4 配置url
# newapp/urls.py
from django.urls import path
from rest_framework.routers import SimpleRouter
from .views import CategoryViewSet, ProductViewSet, SupplierViewSet# 创建一个默认的路由器实例
router = DefaultRouter()# 注册视图集到路由器
router.register(r'categories', CategoryViewSet)
router.register(r'suppliers', SupplierViewSet)
router.register(r'product', ProductViewSet)urlpatterns += router.urls
4.5 测试
4.5.1 查询全部
http://127.0.0.1:8000/drf/product/
[{"id": 1,"name": "空调","category": {"id": 1,"name": "家电","description": ""},"supplier": {"id": 3,"name": "格力","contact_person": "董明珠","email": null,"phone": null},"price": "3459.00","stock_quantity": 100,"description": ""},{"id": 2,"name": "空调","category": {"id": 1,"name": "家电","description": ""},"supplier": {"id": 2,"name": "海信","contact_person": "贾少谦","email": null,"phone": null},"price": "2300.00","stock_quantity": 5,"description": ""},{"id": 3,"name": "电视","category": {"id": 1,"name": "家电","description": ""},"supplier": {"id": 1,"name": "TCL","contact_person": "彭攀","email": null,"phone": null},"price": "2500.00","stock_quantity": 5,"description": ""},{"id": 4,"name": "电视","category": {"id": 1,"name": "家电","description": ""},"supplier": {"id": 2,"name": "海信","contact_person": "贾少谦","email": null,"phone": null},"price": "2700.00","stock_quantity": 2,"description": ""},{"id": 5,"name": "热水器","category": {"id": 2,"name": "厨卫","description": ""},"supplier": {"id": 4,"name": "万家乐","contact_person": "罗潘","email": null,"phone": null},"price": "1600.00","stock_quantity": 5,"description": ""},{"id": 6,"name": "电视","category": {"id": 1,"name": "家电","description": ""},"supplier": {"id": 5,"name": "长虹","contact_person": "柳江","email": null,"phone": null},"price": "2599.99","stock_quantity": 50,"description": "新增库存"}
]
4.5.2 添加产品
http://127.0.0.1:8000/drf/product/
请求体
{"name": "电视888待删除","category_id": 1,"supplier_id": 5,"price": "1222","stock_quantity": 1,"description": ""
}
4.5.3 查询单个产品
http://127.0.0.1:8000/drf/product/1/
4.5.4 修改单个产品
http://127.0.0.1:8000/drf/product/9/
4.5.5 删除单个产品
http://127.0.0.1:8000/drf/product/9/
5、总结
通过上述两个示例,你可以看到使用 `APIView` 和 `ViewSet` 实现 CRUD 操作的不同方式。以下是两者的比较:
5.1 APIView
- - 更细粒度的控制。
- - 适用于需要复杂逻辑的场景。
- - 代码量相对较多,但更灵活。
5.2 ViewSet
- - 自动处理常见的 CRUD 操作。
- - 代码简洁,易于维护。
- - 提供了一致的 URL 结构和行为。
选择哪种方式取决于你的具体需求。如果你需要更多的灵活性和细粒度的控制,可以选择 `APIView`。如果你希望快速实现标准的 CRUD 功能并减少代码量,`ViewSet` 是更好的选择。
希望这个完整的示例对你有帮助!如果有任何问题或需要进一步的解释,请随时提问。
相关文章:

【django】Django REST Framework 构建 API:APIView 与 ViewSet
目录 1、APIView 2、ViewSet 3、APIVIew例子 3.1 模型定义 3.2 序列化器定义 3.3 使用视图 3.3.1 ProductListCreateAPIView 类 3.3.2 ProductRetrieveUpdateDestroyAPIView 类 3.4 配置url 3.5 测试 3.5.1 查询全部 3.5.2 添加产品 3.5.3 查询单个产品 3.5.4 修…...

TOEIC 词汇专题:旅游计划篇
TOEIC 词汇专题:旅游计划篇 制定旅行计划时,尤其是跨国旅游,会涉及到很多独特的英语词汇。以下是与“旅游计划”相关的托业词汇,帮助你更加自如地规划行程。 1. 旅行服务和优惠 出发前了解一下与服务和优惠相关的常用词汇&#…...

第三次RHCSA作业
1、配置网络:为网卡添加一个本网段IPV4地址,x.x.x.123 2、配置yum本地仓库,并完成traceroute命令的安装 yum库配置成功过后,显示这个报错,没能写完 3、用至少两种方法查看sshd服务的进程号 4、添加一块10G大小的磁盘&…...
WebGL(Web Graphics Library)
WebGL(Web Graphics Library)是一种基于 JavaScript 的 API,允许在网页上渲染高性能的 2D 和 3D 图形。它利用计算机的 GPU 来实现硬件加速,因此适合创建游戏、数据可视化和交互式应用程序。 WebGL 的基本概念: 上下文…...

Unity核心笔记
1、认识模型的制作 1.建模 2.展UV 3.材质和纹理贴图 4.骨骼绑定 5.动画制作 总结 2、图片导入概述 1.Unity支持的图片格式 2.图片设置的6大部分 3、纹理类型设置 1.纹理类型主要是设置什么 2.参数讲解 4、纹理形状设置 1.纹理形状主要设置什么 2.参数讲解 5、纹理高级设置 …...
数据挖掘(六)
数据挖掘(六) 文章目录 数据挖掘(六)消除歧义从Twitter下载数据加载数据集并分类文本转换器词袋N元语法其他特征朴素贝叶斯贝叶斯定理朴素贝叶斯算法算法应用实例应用抽取特征将字典转换为矩阵训练朴素贝叶斯分类器组装所有的部件完整代码本文使用朴素贝叶斯进行社会媒体挖…...
Netty 组件介绍 - Channel
主要作用 close()可以用来关闭 channelcloseFuture()用来处理 channel 的关闭sync方法作用是同步等待 channel 关闭而 addListener 方法是异步等待 channel 关闭pipeline()方法添加处理器write()方法将数据写入writeAndFlush()方法将数据写入并刷出...

时间序列预测(十)——长短期记忆网络(LSTM)
目录 一、LSTM结构 二、LSTM 核心思想 三、LSTM分步演练 (一)初始化 1、权重和偏置初始化 2、初始细胞状态和隐藏状态初始化 (二)前向传播 1、遗忘门计算(决定从上一时刻隐状态中丢弃多少信息) 2、…...

Flink CDC 同步 Mysql 数据
文章目录 一、Flink CDC、Flink、CDC各有啥关系1.1 概述1.2 和 jdbc Connectors 对比 二、使用2.1 Mysql 打开 bin-log 功能2.2 在 Mysql 中建库建表准备2.3 遇到的坑2.4 测试 三、番外 一、Flink CDC、Flink、CDC各有啥关系 Flink:流式计算框架,不包含 …...
【python实战】-- 根据文件名分类
系列文章目录 文章目录 系列文章目录前言一、根据文件名分类到不同文件夹总结 前言 一、根据文件名分类到不同文件夹 汇总指定目录下所有满足条件的文件到新文件夹 import os import shutil import globsource_dir rD:\Users\gxcaoty\Desktop\39642 # 源目录路径 destinatio…...
蓝桥双周赛 第21场 小白入门赛
1 动态密码 思路:可以直接填空也可以写程序 void solve() {int a 20241111;stack<int> stk;while(a){stk.push(a % 2);a / 2;}while(stk.size()){cout << stk.top();stk.pop();}} 2 购物车里的宝贝 思路:总体异或和为0即可说明可分成一样…...

Linux 进程间通信 共享内存_消息队列_信号量
共享内存 共享内存是一种进程间通信(IPC)机制,它允许多个进程访问同一块内存区域。这种方法可以提高效率,因为数据不需要在进程之间复制,而是可以直接在共享的内存空间中读写。 使用共享内存的步骤通常包括:…...

Mybatis自定义日志打印
一,目标 替换?为具体的参数值统计sql执行时间记录执行时间过长的sql,并输出信息到文档(以天为单位进行存储) 平常打印出来的sql都是sql一行,参数一行。如图: 二,理论 这里我们主要通过Mybatis…...

【在Linux世界中追寻伟大的One Piece】Socket编程TCP(续)
目录 1 -> V2 -Echo Server多进程版本 2 -> V3 -Echo Server多线程版本 3 -> V3-1 -多线程远程命令执行 4 -> V4 -Echo Server线程池版本 1 -> V2 -Echo Server多进程版本 通过每个请求,创建子进程的方式来支持多连接。 InetAddr.hpp #pragma…...
面试高频问题:C/C++编译时内存五个分区
在面试时,C/C++编译时内存五个分区是经常问到的问题,面试官通过这个问题来考察面试者对底层的理解。在平时开发时,懂编译时内存分区,也有助于自己更好管理内存。 目录 内存分区的定义 内存分区的重要性 代码区 数据区 BSS区 堆区 栈区 静态内存分配 动态内存分配…...

阅读博士论文《功率IGBT模块健康状态监测方法研究》
IGBT的失效可以分为芯片级失效和封装级失效。其中封装级失效是IGBT模块老化的主要原因,是多种因素共同作用的结果。在DBC的这种结构中,流过芯片的负载电流通过键合线传导到 DBC上层铜箔,再经过端子流出模块。DBC与芯片和提供机械支撑的基板之…...
Spring ApplicationContext接口
ApplicationContext接口是Spring框架中更高级的IoC容器接口,扩展了BeanFactory接口,提供了更多的企业级功能。ApplicationContext不仅具备BeanFactory的所有功能,还增加了事件发布、国际化、AOP、资源加载等功能。 ApplicationContext接口的…...

[perl] 数组与哈希
数组变量以 符号开始,元素放在括号内 简单举例如下 #!/usr/bin/perl names ("a1", "a2", "a3");print "\$names[0] $names[0]\n"; print "size: ",scalar names,"\n";$new_names shift(names); …...

电机学习-SPWM原理及其MATLAB模型
SPWM原理及其MATLAB模型 一、SPWM原理二、基于零序分量注入的SPWM三、MATLAB模型 一、SPWM原理 SPWM其实是相电压的控制方式,定义三相正弦相电压的表达式: { V a m V m sin ω t V b m V m sin ( ω t − 2 3 π ) V c m V m sin ( ω t 2…...

群控系统服务端开发模式-应用开发-腾讯云上传工厂及七牛云上传工厂开发
记住业务流程图,要不然不清楚自己封装的是什么东西。 一、腾讯云工厂开发 切记在根目录下要安装腾讯云OSS插件,具体代码如下: composer require qcloud/cos-sdk-v5 在根目录下extend文件夹下Upload文件夹下channel文件夹中,我们修…...

循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
土建施工员考试:建筑施工技术重点知识有哪些?
《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...
文件上传漏洞防御全攻略
要全面防范文件上传漏洞,需构建多层防御体系,结合技术验证、存储隔离与权限控制: 🔒 一、基础防护层 前端校验(仅辅助) 通过JavaScript限制文件后缀名(白名单)和大小,提…...