#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屬性
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並傳入request。url
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實例對象對象
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返回什麼,用戶看到什麼