viewsets.ViewSet 详解

目录

零、前提(这一段可以忽略)

一、地址

二、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_actioncustom_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');

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_喵酱_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值