一、django原生View:
1、启动程序,预加载一条url,执行as_view(),返回view函数
path(‘book/‘, views.BookView.as_view()),
2、用户访问执行view方法,进入到dispatch:
3、dispatch返回执行self.get的值,view调用的dispatch,视图类BookView调用的view,所以视图的返回值就是dispatch的返回值,dispatch的返回值就是view的返回值,即返回给页面的值。
二:使用rest_framework.views.APIView的请求流程:
re_path(‘^book/(\d+)‘, views.BookDetailView.as_view()),
1、APIView继承django的原生View,APIView下的as_view方法返回父类的as_view的返回值view
2、用户访问执行view方法,进入到dispatch:APIView下实现了dispatch方法,所以优先执行APIView下的dispatch:
3、dispatch的执行返回response,response等于视图的返回值。view调用的dispatch,视图类BookView调用的view,所以视图的返回值就是response,也就是dispatch的返回值,dispatch的返回值就是view的返回值,即返回给页面的值。
三、 rest_framework.generics.GenericAPIView:它只是在APIView下进行了简单的封装,将原来实现视图的冗余代码封装在几个不同的类下
path(‘author/‘, views.AuthorView.as_view()),
class AuthorView(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView): queryset = models.Author.objects.all() serializer_class = serializers.AuthorSerializers def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs)
1、程序加载依次向父类查看as_view方法,mixins.ListModelMixin, mixins.CreateModelMixin下都没找到,generics.GenericAPIView下也没有,但它继承APIView,APIView下有,执行它,返回view。
2、用户访问执行view,view的返回值就是dispatch的返回值,这时执行优先执行APIView下的dispatch,dispatch的返回值就是视图的返回值
3、回到视图,视图的返回值时list方法的返回值,视图类没有实现list方法,依次向父类查找
4、mixins.ListModelMixin拥有list方法,执行它,它返回序列化后的数据,也就是视图返回的数据,然后返回给dispatch,再到view。但是这过程是如何实现的呢,先看get_queryset方法
5、get_queryset:在generics.GenericAPIView下找到了这个方法
6、list调的get_queryset,视图调的list,所以self.queryset就是视图类下的queryset
7、list方法将我们在视图中给到的queryset对象序列化后返回
四、viewsets.ModelViewSet中的ViewSetMixin
path(‘book/‘, views.BookView.as_view({‘get‘: ‘list‘, ‘post‘: ‘create‘})),
1、程序初识化执行as_view,它在ViewSetMixin下,不在是django原生View下的as_view,此时它接收一个action参数,即url地址中给的字典
2、用户访问,执行view,此时"get","post"等字符串等于self.list和self.creater
3、一步一步查dispatch,ViewSetMixin下没有实现,GenericAPIView也没有实现,GenericAPIView继承APIView,APIView实现了
4、执行APIView下的dispatch,返回self.list的执行
5、找self.list,发现它就是ListModelMixin类下的list方法
总结:
视图类继承django原生views.View时:as_view()返回view,它的返回值等于dispatch的返回值,dispatch的返回值等于视图类下get、post等方法的执行
视图类继承rest_framework下的APIView时,as_view()依然执行的是原生View类下的as_view,但是APIView覆盖了dispatch方法,所以view的返回值是APIView下的dispatch执行。它重构了一个新的request
由于使用上面两种方式实现视图时,冗余代码过多,mixins类能够精简代码:
继承ListCreateAPIView和RetrieveUpdateDestroyAPIView类,只需要提供queryset对象与序列化类即可。as_view与dispatch的执行与APIView一致,只是最后一步视图中get、post等方法的执行被封装在mixins类中。
viewsets.ModelViewSet类能够通过url实现所有请求方式只用一个CBV即可实现。主要是as_view的执行不再是原生View类下的as_view,而是ViewSetMixin下的as_view。它返回的view在用户访问执行时,url中的字典对应的执行方法在view方法经过对照处理,执行到dispatch时,他能够在mixins类中找到对应的执行类和方法,例如self.list、self.create