DRF学习笔记(五):视图集ViewSet


前言

使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:

  • list() 提供一组数据
  • retrieve() 提供单个数据
  • create() 创建数据
  • update() 更新保存数据
  • destory() 删除数据
    ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等。

视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上。如:

from rest_framework.response import Response
from demo.models import ClassInfo
from demo.serializers import ClassInfoSerializer
from rest_framework import viewsets, status
class ClassViewSet(viewsets.ViewSet):
    # 获取所有班级数据
    def list(self, request):
        Classes = ClassInfo.objects.all()
        serializer = ClassInfoSerializer(Classes, many=True)
        return Response(serializer.data)
    
    def retrieve(self, request, pk=None):
        try:
            Class = ClassInfo.objects.get(id=pk)
        except ClassInfo.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
        serializer = ClassInfoSerializer(Class)
        return Response(serializer.data)

在设置路由是,我们可以如下操作
demo/uels.py

from django.urls import path
from demo import views
urlpatterns = [
	······
    path('classes/', views.ClassViewSet.as_view({'get': 'list'})),
    path('classes/<int:pk>/', views.ClassViewSet.as_view({'get': 'retrieve'})),
]

结果:
在这里插入图片描述
在这里插入图片描述

一、常用视图集父类

1) ViewSet

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

ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典(如{‘get’:‘list’})的映射处理工作。

在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。

2)GenericViewSet

使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与GenericAPIView,所以还需要继承GenericAPIView。

GenericViewSet就帮助我们完成了这样的继承工作,继承自GenericAPIView与ViewSetMixin,在实现了调用as_view()时传入字典(如{‘get’:‘list’})的映射处理工作的同时,还提供了GenericAPIView提供的基础方法,可以直接搭配Mixin扩展类使用。

举例:

from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action
class ClassInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
    queryset = ClassInfo.objects.all()
    serializer_class = ClassInfoSerializer

url的定义
demo/urls.py

urlpatterns = [
    ······
    path('classes_set/', views.ClassInfoViewSet.as_view({'get': 'list'})),
    path('classes_set/<int:pk>/', views.ClassInfoViewSet.as_view({'get': 'retrieve'})),
]

结果和上面的一样:
在这里插入图片描述
在这里插入图片描述

二、视图集中定义附加action动作

在视图集中,除了上述默认的方法动作外,还可以添加自定义动作。

添加自定义动作需要使用rest_framework.decorators.action装饰器。

以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。

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

  • methods: 该action支持的请求方式,列表传递
  • detail: 表示是action中要处理的是否是视图资源的对象(即是否通过url路径获取主键)
    (1)True 表示使用通过URL获取的主键对应的数据对象
    (2)False 表示不使用URL获取主键
    举例:
from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action
class ClassInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
   queryset = ClassInfo.objects.all()
   serializer_class = ClassInfoSerializer

   # detail为False 表示不需要处理具体的BookInfo对象
   @action(methods=['get'], detail=False)
   def latest(self, request):
       """返回id最后的一个班级"""
       Class = ClassInfo.objects.latest('id')
       serializer = ClassInfoSerializer(Class)
       return Response(serializer.data)

   # detail为True,表示要处理具体与pk主键对应的BookInfo对象
   @action(methods=['put'], detail=True)
   def updata(self, request, pk):
       """修改班级信息"""
       Class = self.get_object()
       Class.number = request.data.get('number')
       Class.grade = request.data.get('grade')
       Class.save()
       serializer = self.get_serializer(Class)
       return Response(serializer.data)

url的定义
demo/urls.py

from django.contrib import admin
from django.urls import path, include
from demo import views
urlpatterns = [
······
 path('classes_set/<int:pk>/', views.ClassInfoViewSet.as_view({'get': 'retrieve', 'put': 'updata'})),
 path('classes_set_latest/', views.ClassInfoViewSet.as_view({'get': 'latest'})),
]

结果:
在这里插入图片描述
在这里插入图片描述

结束

drf的基本内容就讲完了,不懂的可以在评论区留言。

补充

有时候我们自定义的动作太多,添加路径的时候不方便,所以drf为我们贴心的提供了路由功能,自动为视图集生成路径。
使用:将原来的路由注释,添加如下代码

from django.contrib import admin
from django.urls import path, include, re_path
from demo import views
from rest_framework.routers import DefaultRouter

# urlpatterns = [
#     path('classes_set/<int:pk>/', views.ClassInfoViewSet.as_view({'get': 'retrieve', 'put': 'updata'})),
#     path('classes_set_latest/', views.ClassInfoViewSet.as_view({'get': 'latest'})),
# ]
# 定义总路径
urlpatterns = []
# 定义路由
classes_router = DefaultRouter()
# 注册路由
classes_router.register("classes_set", views.ClassInfoViewSet, basename="classes_set")
# 将注册路由的路径添加到总路径中
urlpatterns += classes_router.urls

其中,register里面的参数是register(路由前缀,视图集,basename)
访问时的路径则变为: (前缀)/路由前缀/函数名
结果不变(注意路径发生了变化):
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值