使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:
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扩展类使用。
代码应用:
# 视图集(获取所有,获取单一)
# url(r'^books/$', views.BookInfoViewSet.as_view({'get': 'list'})), # book-list
# url(r'^books/(?P\d+)/$', views.BookInfoViewSet.as_view({'get': 'retrieve'})), #book-retrieve
from rest_framework.viewsets import GenericViewSet
from rest_framework import mixins
from .models import BookInfo, HeroInfo
from .serializers import BookInfoSerializer
class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
3)ModelViewSet
继承自GenericViewSet
,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。
4)ReadOnlyModelViewSet
继承自GenericViewSet
,同时包括了ListModelMixin、RetrieveModelMixin。
代码应用:
from rest_framework.viewsets import ReadOnlyModelViewSet
from .models import BookInfo, HeroInfo
from .serializers import BookInfoSerializer
# ReadOnlyModelViewSet包含上面继承的三个类
class BookInfoModelViewSet(ReadOnlyModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
在视图集中,除了上述默认的方法动作外,还可以添加自定义动作。
# todo:action装饰器
from rest_framework.decorators import action
from rest_framework.viewsets import GenericViewSet
from rest_framework import mixins
from .models import BookInfo, HeroInfo
from .serializers import BookInfoSerializer
class BookInfoViewSetAction(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
queryset = BookInfo.objects.all()
def get_serializer_class(self):
if self.action == 'read':
return BookReadSerializer
else:
return BookInfoSerializer
@action(methods=['get'], detail=False)
def latest(self, request):
"""
返回最新的书籍
:param request:
:return:
"""
book = BookInfo.objects.latest('id')
serializer = self.get_serializer(book)
return Response(serializer.data)
@action(methods=['put'], detail=True)
def read(self, request):
"""
修改书记的阅读量
:param request:
:return:
"""
book = self.get_object()
serializer = self.get_serializer(instance=book, data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)