Django Rest Framework----ModelViewSet视图 ModelViewSet源码分析

一、视图类

#bookview是一个视图类,继承自ModelViewSet
class BookView(ModelViewSet):
    throttle_classes = [VisitThrottle2]
    queryset = models.Book.objects.all()
    serializer_class = BookModelSerializer

ModelViewSet

ModelViewSet:
        class ModelViewSet(mixins.CreateModelMixin,    # 实现了post添加逻辑
                   mixins.RetrieveModelMixin,          # 实现了获取具体某一本书的逻辑
                   mixins.UpdateModelMixin,            # 实现了put编辑的逻辑
                   mixins.DestroyModelMixin,           # 实现了删除一本书的逻辑
                   mixins.ListModelMixin,              # 实现了获取所有书的逻辑
                   GenericViewSet):                    # 提供了APIView和dispatch的功能
....
由于ModelViewSet继承了多个混合类和通用视图类,所以ModelViewSet提供了.list(),.retrieve(), .create(),.update(),.partial_update(),和.destroy()
因为ModelViewSet继承了GenericViewSet,所以BookView需要提供queryset和serializer_class属性

 

二、执行流程

1. url:

url(r'books/$',views.BookView.as_view({'get':'list','post':'create'})),
url(r'books/(?P<pk>\d+)/$',views.BookDetailView.as_view({'get': 'retrieve',
                                                             'put':'update',
                                                             'delete':'destroy'})),

当django启动的时候,会执行view.BookView.as_view()方法:由于as_view()是从ViewSetMixin中继承而来的,所以url会变为:

url(r'books/$',ViewSetMixin.view),
url(r'books/(?P<pk>\d+)/$',ViewSetMixin.view),

2.当用户访问books/的时候,会调用执行ViewSetMixin.view并传入request

class ViewSetMixin(object):
         """
            他是一个魔法方法
            重写`.as_view()‘,以便它接受一个’actions‘关键字,
            该关键字执行HTTP方法到资源上的操作的绑定。
            例如,要创建一个将“GET”和“POST”方法绑定到“List”和“Create”操作的具体视图.
            view = MyViewSet.as_view({'get': 'list', 'post': 'create'})
        """
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            self.action_map = actions

            # {'get':'list','post':'create'}
            # {'get': 'retrieve','put':'update','delete':'destroy'}

            for method, action in actions.items():
                # self:ModelViewSet继承的每一个类 action是list create等方法。
                # handler是每一个具体的函数名
                handler = getattr(self, action)
                #为属性赋值, self.get = list, self.get = retrieve
                # 当get请求的时候,真正会执行的是list/retrieve方法
                setattr(self, method, handler)

            # 进行分发,由于以上几个类都没有实现该方法,所以dispatch()执行的是APIView的dispatch()
            return self.dispatch(request, *args, **kwargs)

3.ViewSetMixin的view主要是把mixins中的list()、create()、retrieve()、等绑定给BookView的get()、post()等

4.dispatch()

def dispatch(self, request, *args, **kwargs):

            try:
                self.initial(request, *args, **kwargs)

                # get、put、post等请求方法,去list、create、update等,去执行
                if request.method.lower() in self.http_method_names:

                    # 这里的self是ViewSetMixin。
                    handler = getattr(self, request.method.lower(),
                                      self.http_method_not_allowed)
                else:
                    handler = self.http_method_not_allowed

                response = handler(request, *args, **kwargs)

            except Exception as exc:
                response = self.handle_exception(exc)

            self.response = self.finalize_response(request, response, *args, **kwargs)
            return self.response

当客户端请求方式是get的时候,执行BookView的get()方法,实际上是执行的list().因为在ViewSetMixin.view()中,获取minx下的list、create等函数地址,通过settattr()的方式绑给了BookView实例对象

三、总结:

django启动******

        url(r'books/$',views.BookView.as_view({'get':'list','post':'create'})),   1
            url(r'books/$',ViewSetMixin.view)),    2

    一旦用户访问******

        books  get请求

         def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            {'get':'list','post':'create'}

            for method, action in actions.items():

                handler = getattr(self, action)
                #给BookView设置一个属性  BookView.get = ListModelMixin.list
                setattr(self, method, handler)

            return self.dispatch(request, *args, **kwargs)

         url(r'books/$',APIView.dispatch)),  3

         if get in self.http_method_names:

            # 这里的self是ViewSetMixin。
            handler = getattr(self, 'get'),  --> BookView.get ---> 实际上执行的是 ListModelMixin.list
                              self.http_method_not_allowed)


         handler返回什么,dispatch返回什么,view返回什么,用户看到什么

 

posted @ 2018-06-22 10:08  短毛兔  阅读(6737)  评论(0编辑  收藏  举报