Django rest framework视图集

#Django rest framework视图集

Django REST框架允许将一组相关视图的逻辑组合到一个类中,称为ViewSet

一个ViewSet类只是一种基于类的View,它不提供任何方法处理程序(如get()orpost()),而是提供诸如list()和create()之类的操作。

使用ViewSet类比使用View类有两个主要优点。

重复的逻辑可以合并成一个类。例如我们只需要指定queryset一次,它将用于多个视图。
通过使用路由器,我们不再需要处理自己的URL配置

###1ViewSet
一个ViewSet类只是一种基于类的View,继承自APIView,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。

在ViewSet中,它不提供任何方法处理程序,需要我们自己重写该类并明确实现action方法。

class BookViewSet(viewsets.ViewSet):

    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类同时提供以下可用属性

basename- 用于创建的URL名称的基础。
action- 当前动作的名称(例如list,create)。
detail- 布尔值,指示当前操作是否为列表或详细视图配置。
suffix- 视图类型的显示后缀 - 镜像detail属性。

from rest_framework.viewsets import ViewSet
from django.shortcuts import get_object_or_404
from rest_framework.response import Response

class BookViewSet(ViewSet):

    def list(self,request):
        queryset = BookInfo.objects.all()
        serializer = BookInfoSerializer(queryset,many=True)
        return Response(serializer.data)

    def retrieve(self,request,pk=None):
        queryset = BookInfo.objects.all()
        user = get_object_or_404(queryset, pk=pk)
        serializer = BookInfoSerializer(user)
        return Response(serializer.data)

在设置路由时,我们可以如下操作

from rest_framework.routers import DefaultRouter

rounter = DefaultRouter()
rounter.register(r'books',views.BookViewSet,base_name='')


urlpatterns = [
    # url(r'^books/$',views.BookViewSet.as_view({'get':'list'})),
    # url(r'^books/(?P\d+)/$',views.BookViewSet.as_view({'get':'retrieve'})),

]

urlpatterns += rounter.urls

###2.GenericViewSet
继承自GenericAPIView,作用也与GenericAPIVIew类似,提供了get_object、get_queryset等方法便于列表视图与详情信息视图的开发。在GenericAPIView中,没有提供任何动作action方法,需要我们自己覆盖该类并混合所需的混合类,或者明确定义操作实现action方法

###3.ModelViewSet
继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。

ModelViewSet类所继承GenericAPIView,包括用于各种动作实现方式中,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。

由提供的动作ModelViewSet类是.list(),.retrieve(),.create(),.update(),.partial_update(),和.destroy()

使用:

因为ModelViewSet扩展GenericAPIView,我们通常需要提供至少queryset和serializer_class属性

class BookListModelViewSet(ModelViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

在设置路由时,我们可以如下操作

router = DefaultRouter()
router.register(r'books',views.BookListModelViewSet)

urlpatterns = [
    url(r'^',include(router.urls)),
    # url(r'^books/$', BookViewSet.as_view({'get': 'list'})),
    # url(r'^books/(?P\d+)/$', BookViewSet.as_view({'get': 'retrieve'})),
]

视图集中定义附加action动作
如果你有特别的方法应该是可路由的,你可以用@action装饰器来标记它们。像常规操作一样,额外的操作可以用于对象列表或者单个实例。为了表明是否是单个实例,将detail参数设置为True

method指明请求方式,detail用于控制是否使用一组对象还是一个对象。

from rest_framework.decorators import action
from rest_framework import status
class BookListModelViewSet(ModelViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    #detail为True表示单个实例,网址为这种形式:^books/{pk}/set_bookname/$
    @action(methods=['post'], detail=True)
    def set_bookname(self, request, pk=None):
        book = self.get_object()
        serializer = BookInfoSerializer(data=request.data)
        if serializer.is_valid():
            book.name = request.data['name']
            book.save()
            return Response({'message': '重置成功'})
        else:
            return Response(serializer.errors,
                            status=status.HTTP_400_BAD_REQUEST)

    #detail为False表示列表,网址为这种形式:^books/order_comment/$
    @action(detail=False)
    def order_comment(self, request):
        books = BookInfo.objects.all().order_by('-commentcount')
        serializer = self.get_serializer(books, many=True)
        return Response(serializer.data)

路由设置不变

from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r'books',views.BookListModelViewSet)
urlpatterns = [
    url(r'^',include(router.urls)),
    # url(r'^books/$', BookViewSet.as_view({'get': 'list'})),
    # url(r'^books/(?P\d+)/$', BookViewSet.as_view({'get': 'retrieve'})),
]

###4.ReadOnlyModelViewSet
继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin。

与ModelViewSet它一样,它还包括各种操作的实现,但不同于ModelViewSet只提供“只读”操作,list()而且retrieve()

###5.路由Router
对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由列表信息。

REST framework提供了两个router

SimpleRouter
DefaultRouter

1. 使用方法
1) 创建router对象,并注册视图集,注册语法为

register(prefix, viewset,base_name)
#prefix 该视图集的路由前缀
#viewset 视图集
#base_name 路由名称的前缀

from rest_framework import routers

router = routers.SimpleRouter()
router.register(r'books', BookViewSet, base_name='book')

#如上述代码会形成的路由如下:

^books/$    name: book-list
^books/{pk}/$   name: book-detail

2)添加路由数据

可以有两种方式:

urlpatterns = [
    ...
]
urlpatterns += router.urls
urlpatterns = [
    ...
    url(r'^', include(router.urls))
]

视图集中包含附加动作的

from rest_framework.decorators import action
from rest_framework import status
class BookListModelViewSet(ModelViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    #detail为True表示单个实例,网址为这种形式:^books/{pk}/set_bookname/$
    @action(methods=['post'], detail=True)
    def set_bookname(self, request, pk=None):
        book = self.get_object()
        serializer = BookInfoSerializer(data=request.data)
        if serializer.is_valid():
            book.name = request.data['name']
            book.save()
            return Response({'message': '重置成功'})
        else:
            return Response(serializer.errors,
                            status=status.HTTP_400_BAD_REQUEST)

    #detail为False表示列表,网址为这种形式:^books/order_comment/$
    @action(detail=False)
    def order_comment(self, request):
        books = BookInfo.objects.all().order_by('-commentcount')
        serializer = self.get_serializer(books, many=True)
        return Response(serializer.data)
#此视图集会形成的路由:

detail为True: ^books/{pk}/set_bookname/$    name: books-set-bookname
detail为False: ^books/order_comment/$       name: books-order-comment

3. 路由router形成URL的方式

DefaultRouter与SimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据。

你可能感兴趣的:(django)