三、几种视图实现源码剖析:django原生View、rest_framework.views.APIView、rest_framework.generics.GenericAPIView、ViewSetMixin

一、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的返回值,即返回给页面的值。

扫描二维码关注公众号,回复: 10040396 查看本文章

二:使用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

猜你喜欢

转载自www.cnblogs.com/aizhinong/p/12543799.html