视图集

ModelViewSet继承了5个视图扩展类和GenericViewSet

class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
    pass

GenericViewSet又继承了ViewSetMixin和GenericAPIView

class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
    pass

ViewSet继承了ViewSetMixin和APIView,这两个类里面都有as_view方法,继承的时候,把ViewSetMixin写在前面,APIView写在后面

class ViewSet(ViewSetMixin, views.APIView):

ViewSetMixin有个as_view方法

只要继承了ViewSetMixin,路由就要写成字典形式,由以下源码决定的

ViewSetMixin源码分析

class ViewSetMixin:	
    @classonlymethod
	def as_view(cls, actions=None, **initkwargs):
		...
        def view(request, *args, **kwargs):
        	...
            self.action_map = actions

                # Bind methods to actions
                # This is the bit that's different to a standard view
            for method, action in actions.items():
                handler = getattr(self, action)
                setattr(self, method, handler)
            ...
            return self.dispatch(request, *args, **kwargs)
        
# urls.py 中要给actions参数传值
path('books4/',views.BooksView4.as_view(actions={'get':'list','post':'create'})),
    re_path('books4/(?P<pk>\d+)',views.BooksView4.as_view(actions={'get':'retrieve','put':'update','delete':'destroy'})),

自动生成路由

# 第一步导入
from rest_framework import routers
# 第二步生成对象
router = routers.SimpleRouter()		#DefaultRouter,SimpleRouter生成两条路由

# 第三步注册 router.register('前缀', 视图类),可以为多个视图类注册
router.register('books4', views.BooksView4)
# 第四步:把router.urls(是个列表)加到urlpatterns中
from django.urls import path,re_path,include
urlpatterns += router.urls
# 或者
urlpatterns = [
    ...
	path('',include(router.urls))
]
'''
^books4/$ [name='book-list']
^books4/(?P<pk>[^/.]+)/$ [name='book-detail']
'''

action

给继承了ModelViewSet的视图类中定义的函数也添加路由

from rest_framework.decorators import action

class BooksView4(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer
	# detail=True参数控制:生成的路由是否带pk,methods是可以接收的请求方式
    @action(methods=['get','post'],detail=True)
    def get_data(self,request,pk):
        book=self.get_queryset()[:2]
        ser=self.get_serializer(book,many=True)
        return Response(ser.data)
    
'''
^books4/(?P<pk>[^/.]+)/get_data/$ [name='book-get-data']
'''