Django Rest Framework----ModelViewSet視圖 ModelViewSet源碼分析

1、視圖類

#bookview是一個視圖類,繼承自ModelViewSet
class BookView(ModelViewSet):
    throttle_classes = [VisitThrottle2]
    queryset = models.Book.objects.all()
    serializer_class = BookModelSerializer

ModelViewSetdjango

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屬性

 

2、執行流程

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會變爲:post

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

2.當用戶訪問books/的時候,會調用執行ViewSetMixin.view並傳入requesturl

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()等spa

4.dispatch()code

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實例對象對象

3、總結:

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返回什麼,用戶看到什麼
相關文章
相關標籤/搜索