使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:
视图集只在使用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//' , views.ClassViewSet.as_view({
'get': 'retrieve'})),
]
继承自APIView与ViewSetMixin,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。
ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典(如{‘get’:‘list’})的映射处理工作。
在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。
使用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//' , views.ClassInfoViewSet.as_view({
'get': 'retrieve'})),
]
在视图集中,除了上述默认的方法动作外,还可以添加自定义动作。
添加自定义动作需要使用rest_framework.decorators.action装饰器。
以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。
action装饰器可以接收两个参数:
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//' , views.ClassInfoViewSet.as_view({
'get': 'retrieve', 'put': 'updata'})),
path('classes_set_latest/', views.ClassInfoViewSet.as_view({
'get': 'latest'})),
]
drf的基本内容就讲完了,不懂的可以在评论区留言。