目录
零、前提(这一段可以忽略)
一、地址
二、viewsets.ViewSet介绍
2.1 viewsets.ViewSet介绍
三、viewsets.ViewSet默认方法(增删改查等方法)
四、 生成路由
4.1 使用路由器注册 viewset,自动生成 URL 配置(推荐)
4.2 自定义路由
五、ViewSet actions
五、反射ViewSet actions
六、自定义actions
6.1、http请求put方法、delete方法
八、获取操作的URL
相关文章:
Django项目生成Swagger_做测试的喵酱的博客-CSDN博客
viewsets.ModelViewSet详解_做测试的喵酱的博客-CSDN博客
零、前提(这一段可以忽略)
1、我先创建一个Django项目,Projects app。
python3 manage.py startapp Projects
2、setting.py 注册 Projects app
3、定义模型类models.py
from django.db import models
class Projects(models.Model):
id = models.AutoField(verbose_name='id主键', primary_key=True, help_text='id主键')
name = models.CharField('项目名称', max_length=200, unique=True, help_text='项目名称')
leader = models.CharField('负责人', max_length=50, help_text='项目负责人')
tester = models.CharField('测试人员', max_length=50, help_text='项目测试人员')
programmer = models.CharField('开发人员', max_length=50, help_text='开发人员')
publish_app = models.CharField('发布应用', max_length=100, help_text='发布应用')
desc = models.CharField('简要描述', max_length=200, null=True, blank=True, default='', help_text='简要描述')
update_datetime = models.DateTimeField(auto_now=True, null=True, blank=True, help_text="修改时间",
verbose_name="修改时间")
create_datetime = models.DateTimeField(auto_now_add=True, null=True, blank=True, help_text="创建时间",
verbose_name="创建时间")
class Meta:
db_table = 'tb_projects'
verbose_name = '项目信息'
verbose_name_plural = verbose_name
ordering = ('id',)
def __str__(self):
return self.name
4、序列化器类serializers.py
# -*- coding:utf-8 -*-
# @Author: 喵酱
# @time: 2023 - 07 -04
# @File: serializers.py
# desc:
from rest_framework import serializers
from .models import Projects
class ProjectsModelSerializer(serializers.ModelSerializer):
class Meta:
model = Projects
exclude = ('update_datetime', )
extra_kwargs = {
"create_datetime": {
"read_only": True,
"format": "%Y年%m月%d日 %H:%M:%S"
}
}
一、地址
官方地址:
Viewsets - Django REST framework
相关文章:
二、viewsets.ViewSet介绍
2.1 viewsets.ViewSet介绍
1、引入:
from rest_framework import viewsets
2、 viewsets.ViewSet
是一个提供了用于处理 CRUD(创建、读取、更新和删除)操作的视图集合。
- .list():列出所有项目的列表,
- .retrieve():检索某一个项目的详细信息
- .create() : 创建一条数据
- update(): 更新列表
- .partial_update():更新一条数据
- .destroy():删除数据
以上方法,是定义的默认方法。需要自己在方法下,补充具体的实现逻辑。
3、继承关系
class ViewSet(ViewSetMixin, views.APIView):
4、项目架构
三、viewsets.ViewSet默认方法(增删改查等方法)
- .list():列出所有项目的列表,
- .retrieve():检索某一个项目的详细信息
- .create() : 创建一条数据
- .update(): 更新列表
- .partial_update():更新一条数据
- .destroy():删除数据
自定义视图类ProjectsViewSet,继承viewsets.ViewSet。手动实现以上方法的逻辑。
from django.shortcuts import render
# Create your views here.
from rest_framework import viewsets, status
from .models import Projects
from .serializers import ProjectsModelSerializer
from rest_framework.response import Response
from rest_framework import viewsets
from rest_framework.response import Response
from .serializers import ProjectsModelSerializer
from .models import Projects
class ProjectsViewSet(viewsets.ViewSet):
def list(self, request):
"""
获取所有项目列表
"""
# 获取所有项目对象
projects = Projects.objects.all()
# 将项目对象序列化为 JSON 数据
serializer = ProjectsModelSerializer(projects, many=True)
return Response(serializer.data)
def create(self, request):
"""
创建新的项目
"""
# 将请求数据传递给序列化器
serializer = ProjectsModelSerializer(data=request.data)
if serializer.is_valid():
# 保存新创建的项目对象
serializer.save()
return Response(serializer.data, status=201)
else:
return Response(serializer.errors, status=400)
def retrieve(self, request, pk=None):
"""
获取特定项目详情
"""
# 获取特定的项目对象
project = Projects.objects.get(pk=pk)
serializer = ProjectsModelSerializer(project)
return Response(serializer.data)
def update(self, request, pk=None):
"""
更新特定项目
"""
# 获取特定的项目对象
project = Projects.objects.get(pk=pk)
# 将请求数据与项目对象绑定
serializer = ProjectsModelSerializer(project, data=request.data)
if serializer.is_valid():
# 保存更新后的项目对象
serializer.save()
return Response(serializer.data)
else:
return Response(serializer.errors, status=400)
def destroy(self, request, pk=None):
"""
删除特定项目
"""
# 获取特定的项目对象
project = Projects.objects.get(pk=pk)
# 从数据库中删除项目
project.delete()
return Response(status=204)
def partial_update(self, request, pk=None):
"""
部分更新特定项目
"""
# 获取特定的项目对象
project = Projects.objects.get(pk=pk)
# 将请求数据与项目对象绑定,通过 partial=True 允许部分更新
serializer = ProjectsModelSerializer(project, data=request.data, partial=True)
if serializer.is_valid():
# 保存部分更新后的项目对象
serializer.save()
return Response(serializer.data)
else:
return Response(serializer.errors, status=400)
您可以使用路由器将此 ViewSet 注册,以自动生成用于列出和检索用户的必要 URL。
注意:
1、在视图类ProjectsViewSet中,create方法,创建数据。
def create(self, request):
"""
创建新的项目
"""
# 将请求数据传递给序列化器
serializer = ProjectsModelSerializer(data=request.data)
if serializer.is_valid():
# 保存新创建的项目对象
serializer.save()
return Response(serializer.data, status=201)
else:
return Response(serializer.errors, status=400)
serializer.save() 方法,调用的是序列化器类ProjectsModelSerializer 的create方法。
当使用 ModelSerializer
类创建序列化器时,它会自动为你生成默认的 create
方法。这个默认的 create
方法会在视图类调用创建对象的逻辑时被调用。
当你在视图类中调用 serializer.save()
或者 serializer.create(validated_data)
方法时,会触发序列化器中的 create
方法执行。默认的 create
方法会根据传入的验证数据(validated_data)创建并保存模型实例。
如果你在 ModelSerializer
类中重写了 create
方法,并在其中添加了自定义的逻辑,那么在视图类中调用 serializer.save()
或者 serializer.create(validated_data)
方法时,将会执行你自定义的 create
方法。
因此,视图类中的 create
方法和 ModelSerializer
类中的 create
方法在处理创建对象的逻辑时是相关联的。你可以利用这两个方法来完成对对象创建的个性化定制和扩展。
四、 生成路由
4.1 使用路由器注册 viewset,自动生成 URL 配置(推荐)
使用路由器注册 viewset,并自动生成 URL 配置。
urls.py
# -*- coding:utf-8 -*-
# @Author: 喵酱
# @time: 2023 - 07 -04
# @File: urls.py
# desc:
from .views import ProjectsViewSet
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'projects', ProjectsViewSet, basename='projects')
urlpatterns = router.urls
启动项目,查看swagger文档,这就生成了增删改查的接口。
4.2 自定义路由
# -*- coding:utf-8 -*-
# @Author: 喵酱
# @time: 2023 - 07 -04
# @File: urls.py
# desc:
from django.urls import path
from .views import ProjectsViewSet
# 创建一个实例作为视图集
projects_viewset = ProjectsViewSet.as_view({
'get': 'list',
'post': 'create'
})
# 创建一个用于单个项目的实例
project_detail_viewset = ProjectsViewSet.as_view({
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'destroy'
})
urlpatterns = [
path('projects/', projects_viewset, name='projects-list'),
path('projects/<int:pk>/', project_detail_viewset, name='projects-detail'),
]
我们首先将 ProjectsViewSet
视图集实例化为 projects_viewset
。
我们将 "GET" 请求映射到 list
方法,
将 "POST" 请求映射到 create
方法。
然后,我们创建了一个用于单个项目的视图集实例 project_detail_viewset
。
我们将 "GET" 请求映射到 retrieve
方法,
将 "PUT" 请求映射到 update
方法,
将 "PATCH" 请求映射到 partial_update
方法,
将 "DELETE" 请求映射到 destroy
方法。
最后,我们将 URL 映射到相应的视图集方法并命名它们。可以根据需要调整 URL 模式和命名。
五、ViewSet actions
REST framework 中提供的默认路由器将为一组标准的创建/检索/更新/删除样式的操作提供路由,如下所示:
(其实就是第四节讲的内容)
class ProjectsViewSet(viewsets.ViewSet):
"""
Example empty viewset demonstrating the standard
actions that will be handled by a router class.
If you're using format suffixes, make sure to also include
the `format=None` keyword argument for each action.
"""
def list(self, request):
pass
def create(self, request):
pass
def retrieve(self, request, pk=None):
pass
def update(self, request, pk=None):
pass
def partial_update(self, request, pk=None):
pass
def destroy(self, request, pk=None):
pass
五、反射ViewSet actions
在调度期间,ViewSet 上可以使用以下属性:
- basename - 用于创建 URL 名称的基础部分。
- action - 当前动作的名称(例如,list、create)。
- detail - 布尔值,指示当前动作是否为列表视图或详细视图配置的。
- suffix - 视图集类型的显示后缀 - 与 detail 属性相同。
- name - 视图集的显示名称。该参数与 suffix 互斥。
- description - 视图集中各个视图的显示描述。
您可以检查这些属性以根据当前动作调整行为。例如,您可以类似于以下示例将权限限制为除了 list 动作之外的所有权限:
def get_permissions(self):
"""
实例化并返回此视图所需的权限列表。
"""
if self.action == 'list':
permission_classes = [IsAuthenticated]
else:
permission_classes = [IsAdminUser]
return [permission() for permission in permission_classes]
以上示例中,get_permissions()
方法根据当前动作(self.action
)来确定要应用的权限类。如果当前动作是 list
,则使用 IsAuthenticated
权限类;否则,使用 IsAdminUser
权限类。最后,将权限类实例化并作为列表返回。
六、自定义actions
在 Django REST Framework 中,ViewSet 是一个组合了多个动作(actions)的视图类,提供常见的 CRUD(默认的 create/retrieve/update/destroy 操作创建、读取、更新、删除)操作。反射指的是通过反射机制自动识别视图集中定义的动作,并根据它们生成符合 RESTful 风格的 URL。
使用反射可以让你更加方便地管理视图集中的动作,并自动生成对应的 URL 配置。Django REST Framework 为我们提供了 @action
装饰器,使得在视图集中定义和命名动作变得非常容易。
以下是一个示例,演示如何在视图集中使用 @action
装饰器来定义自定义动作:
from rest_framework.decorators import action
class ProjectsViewSet(viewsets.ViewSet):
# GET /projects/custom_action/
@action(detail=False, methods=['get'])
def custom_action(self, request):
# 在这里执行自定义动作的逻辑
return Response("Custom Action")
# GET /projects/1/custom_action_detail/
@action(detail=True, methods=['get'])
def custom_action_detail(self, request, pk=None):
# 获取特定项目对象
project = self.get_object()
# 在这里执行特定项目的自定义动作逻辑
return Response(f"Custom Action for Project {project.id}")
# ...
在上面的示例中,我们在 ProjectsViewSet
中定义了两个自定义动作:custom_action
和 custom_action_detail
。
custom_action
是一个针对集合的动作,它不关联到特定的项目详情。可以通过发送 GET 请求到/projects/custom_action/
执行自定义动作。custom_action_detail
是一个针对特定项目的动作,它关联到特定的项目详情。可以通过发送 GET 请求到/projects/{id}/custom_action_detail/
执行自定义动作。
使用 detail=False
参数,我们告诉 Django REST Framework 这是一个针对集合的动作;
使用 detail=True
参数,我们告诉它这是一个针对特定项目的动作。
在 URL 配置中,Django REST Framework 会自动识别并为我们生成包含这些自定义动作的 URL。因此,你无需手动编写这些 URL,只需在主路由配置中引入视图集,并让框架为你处理 URL 映射。
总之,使用反射ViewSet actions 可以方便地定义自定义动作,并自动生成相应的 URL 配置。
通过使用@action
装饰器,您可以在ViewSet中定义和配置超出标准CRUD操作的额外操作。
@action
装饰器默认会路由GET请求,但也可以通过设置methods参数接受其他HTTP方法。例如:
@action(detail=True, methods=['post', 'delete'])
def unset_password(self, request, pk=None):
...
该装饰器允许您覆盖任何视图集级别的配置,例如permission_classes、serializer_class、filter_backends等:
@action(detail=True, methods=['post'], permission_classes=[IsAdminOrIsSelf])
def set_password(self, request, pk=None):
...
6.1、http请求put方法、delete方法
例如,上述密码设置/取消方法可以合并为一个路由。请注意,附加映射不接受参数。
@action(detail=True, methods=['put'], name='Change Password')
def password(self, request, pk=None):
"""Update the user's password."""
...
@password.mapping.delete
def delete_password(self, request, pk=None):
"""Delete the user's password."""
...
在上面的示例中,我们定义了名为"Change Password"的额外操作,并将其映射到PUT方法。在方法体内,我们可以执行更新用户密码的逻辑。
同时,我们使用.mapping.delete
装饰器将额外操作delete_password
映射到DELETE方法。在该方法内,我们可以执行删除用户密码的逻辑。
通过这种方式,您可以为额外操作定义不同的HTTP方法,以满足您的需求。
八、获取操作的URL
如果您需要获取操作的URL,请使用.reverse_action()方法。这是reverse()方法的一个便利包装,它会自动传递视图的请求对象,并在url_name之前添加.basename属性。
请注意,basename是在ViewSet注册期间由路由器提供的。如果您没有使用路由器,则必须在.as_view()方法中提供basename参数。
使用前面一节的示例:
>>> view.reverse_action('set-password', args=['1'])
'http://localhost:8000/api/users/1/set_password'
另外,您还可以使用由@action装饰器设置的url_name属性。
>>> view.reverse_action(view.set_password.url_name, args=['1'])
'http://localhost:8000/api/users/1/set_password'
.reverse_action()方法的url_name参数应与@action装饰器的相同参数匹配。此外,该方法还可用于反转默认操作,例如list和create。
九、其他
生成迁移脚本:
python manage.py makemigrations
执行迁移:
python manage.py migrate
手动在数据库中,插入数据,sql
INSERT tb_projects VALUES(null,'喵喵项目','张三','里斯','开发A','应用A','','2023-06-13 03:32:13.421713', '2023-06-13 03:32:13.421775');
INSERT tb_projects VALUES(null,'汪汪项目','张三','里斯','开发A','应用A','','2023-06-13 03:32:13.421713', '2023-06-13 03:32:13.421775');
INSERT tb_projects VALUES(null,'阿苗项目','张三','里斯','开发A','应用A','','2023-06-13 03:32:13.421713', '2023-06-13 03:32:13.421775');