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

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

在django中使用CBV編寫視圖:
  一、首先咱們自定義的視圖類須要繼承django.views.View類
  二、在視圖類中定義以'請求方法名稱小'寫爲名稱的方法,這樣在執行不一樣的請求方法的時候就回去自動執行對應的函數
  三、在路由映射的時候,要執行這個試圖類的as_view()方法,注意這個方法繼承自django.views.View數據庫

示例代碼以下:
'views.py'文件:
  from django.views import View
  from django.http import HttpResponsedjango

  class UserInfoView(View):app

    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')post

 

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

上述示例代碼就能夠根據同一個url執行不一樣的方法時去執行不一樣的操做url

 

CBV實現的源碼分析:
  一、請求進來,路由找到試圖類並執行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))spa

    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

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

  三、由於試圖類自己沒有定義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)

 

CBV之添加裝飾器:

在咱們使用函數試圖FBV的時候,若是咱們想要給其加上一個裝飾器,直接加就能夠了,例如,在建立django項目的時候,默認全局使用csrf防禦,若是咱們想要在某個函數試圖上不使用CSRF保護,那麼咱們能夠給這個視圖函數直接添加一個裝飾器便可,示例代碼以下:

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def index(request):
return HttpResponse('index')

 

可是,當咱們想要給CBV添加裝飾器,那麼咱們須要作的就不是在其內部的方法上添加,若是和FBV同樣直接添加到方法上,那麼這不會起任何做用。在CBV上添加裝飾器的方法有兩種,第一種是重寫父類的dispatch方法,並將裝飾器添加到dispatch方法上,與此同時在CBV上添加裝飾器最好使用django.utils.decorators.method_decorator方法進行包裹。第二種方法則是直接添加在類上,只不過這時你須要使用django.utils.decorators.method_decorator來進行封裝。下面的例子是咱們在django中針對重要的數據操做,想要實現數據庫的事件特性而添加的裝飾器:

一、方法一:

from django.utils.decorators import method_decorator
from django.db import transaction

class OrderView(View):
@method_decorator(transaction.atomic)
def dispatch(self, request, *args, **kwargs):
return super(OrderView, self).dispatch(request, *args, **kwargs)

def get(self, request, *args, **kwargs):
pass

def post(self, request, *args, **kwargs):
pass

def patch(self, request, *args, **kwargs):
pass

def delete(self, request, *args, **kwargs):
pass

二、方法二:
from django.utils.decorators import method_decorator
from django.db import transaction

@method_decorator(transaction.atomic, name='dispatch')
class OrderView(View):
def get(self, request, *args, **kwargs):
pass

def post(self, request, *args, **kwargs):
pass

def patch(self, request, *args, **kwargs):
pass

def delete(self, request, *args, **kwargs):
pass
相關文章
相關標籤/搜索