1. 程式人生 > >django類視圖簡單使用和源碼解析

django類視圖簡單使用和源碼解析

很多 bsp valid hasattr assigned else rgs pda argument

django的類視圖,CBV
  我們在開始接觸django的時候,習慣於使用函數編寫視圖,即FBV。使用FBV時,我們只需要在路由匹配時,對應的路由下找到這個函數就可以了,這樣做看似很和諧,但是有的時候,譬如說,當我們需要根據同一個url請求方法的不同而去執行不同的操作時,如果使用FBV去編寫視圖,那麽我們就需要在視圖函數中不斷地去執行if request.method==‘請求方法‘ 去判斷要去執行什麽內容,此時的代碼就顯得不是很優雅。但是此時如果我們使用CBV的方式來編寫視圖,同樣的需求,代碼就會顯得優雅很多,下面就讓我來介紹一下CBV的具體實現:

在django中使用CBV編寫視圖:
  1、首先我們自定義的視圖類需要繼承django.views.View類


  2、在視圖類中定義以‘請求方法名稱小‘寫為名稱的方法,這樣在執行不同的請求方法的時候就回去自動執行對應的函數
  3、在路由映射的時候,要執行這個試圖類的as_view()方法,註意這個方法繼承自django.views.View

示例代碼如下:
‘views.py‘文件:
  from django.views import View
  from django.http import HttpResponse

  class UserInfoView(View):

    def get(self, request, *args, **kwargs):
      return HttpResponse(‘get user‘)

    def post(self, request, *args, **kwargs):
      return HttpResponse(‘post user‘)

    def delete(self, request, *args, **kwargs):
      return HttpResponse(‘delete user‘)

‘url.py‘文件
  from app import views
  urlpatterns = [
    path(‘user/‘, views.UserInfoView.as_view())
  ]

上述示例代碼就可以根據同一個url執行不同的方法時去執行不同的操作

CBV實現的源碼分析:
  1、請求進來,路由找到試圖類並執行as_view方法,執行這個方法時其實會返回一個view函數,因此可以看做請求進來之後會先執行試圖類的view方法,源碼如下:
  @classonlymethod
  def as_view(cls, **initkwargs):
    for key in initkwargs:
      if key in cls.http_method_names:
        raise TypeError("You tried to pass in the %s method name as a "
                "keyword argument to %s(). Don‘t do that."
                % (key, cls.__name__))
      if not hasattr(cls, key):
        raise TypeError("%s() received an invalid keyword %r. as_view "
                "only accepts arguments that are already "
                "attributes of the class." % (cls.__name__, key))

    def view(request, *args, **kwargs):
      self = cls(**initkwargs)
      if hasattr(self, ‘get‘) and not hasattr(self, ‘head‘):
        self.head = self.get
      self.request = request
      self.args = args
      self.kwargs = kwargs
      return self.dispatch(request, *args, **kwargs)
    view.view_class = cls
    view.view_initkwargs = initkwargs

    update_wrapper(view, cls, updated=())

    update_wrapper(view, cls.dispatch, assigned=())
    return view

  2、從上面的源碼中可以看出執行view方法,實際上就是返回self.dispatch方法,也就是說會去執行self.dispatch方法

  3、因為試圖類本身沒有定義dispatch方法,那麽在執行dispatch方法的時候就需要去其父類裏面查找,而父類裏面的dispatch方法則會根據請求方法的不同基於python類的反射去找到相應的方法,然後執行,這樣就會自動實現根據請求方法的不同去執行不同的內容了,dispatch方法的源碼如下:
  def dispatch(self, request, *args, **kwargs):

    if request.method.lower() in self.http_method_names:
      handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    else:
      handler = self.http_method_not_allowed
    return handler(request, *args, **kwargs)

django類視圖簡單使用和源碼解析