第5天:基於類的視圖與中間件

  •  類視圖引入
  •  類視圖的定義與使用
  •  類視圖實現的原理
  •  在類視圖中使用裝飾器
  •  類視圖多繼承&Minx擴展類
  •  中間件

類視圖引入

以函數的方式定義的視圖成爲函數視圖,函數視圖便於理解。可是遇到一個視圖對應的路徑提供了多種不一樣HTTP請求方式的支持時,就須要在一個函數中編寫不一樣的業務邏輯,代碼可讀性與複用性都不佳html

def register(request):
    """處理註冊"""

    #獲取請求方法,判斷是GET/POST請求
    if request.method == 'GET':
        #處理GET請求,返回註冊頁面
        return render(request, 'register.html')
    else:
        #處理POST請求,實現註冊邏輯
        return HttpResponse('這裏實現註冊邏輯')
函數視圖示例

在Django中也可使用類來定義一個視圖,稱爲類視圖django

def register(View):
    """類視圖 處理註冊"""
    
    def get(self, request):
        "處理GET請求, 返回註冊頁面"
        return render(request, 'register.html')
    
    def post(self, request):
        " 處理POST請求,實現註冊邏輯"
        return HttpResponse('這裏實現註冊邏輯')
類視圖示例

類視圖好處:服務器

  • 代碼可讀性好
  • 類視圖相對於函數視圖經過繼承具備更高的可複用性

 

類視圖的定義與使用

咱們要想使用類視圖必須繼承Viewapp

from django.views.generic import View框架

from django.views.generic import View


class DemoView(View):
    def get(self, request):
        return HttpResponse('get page')
    
    def post(self, request):
        return HttpResponse('post page')
DemoView

路由那裏,我則須要使用該視圖的as_view方法轉換爲函數ide

from .views import DemoView

urlpatterns = [
    url(r'^demo/$', DemoView.as_view(), name='demo')
]
路由配置

 

類視圖實現的原理

 按住ctrl,點擊as_view函數

@classonlymethod
def as_view(cls, **initkwargs):
    """
    Main entry point for a request-response process.
    """
    ...

    def view(request, *args, **kwargs):
        self = cls(**initkwargs)     #cls就是DemoView類,生成對象
        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   #最終仍是返回函數

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)
相關源碼

 

在類視圖中使用裝飾器

咱們知道在函數視圖中,能夠以下使用裝飾器 post

def my_decorator(view_func):
    def wrapper(*args, **kwargs):
        print('裝飾器被調用')
        return view_func(*args, **kwargs)
    return wrapper

@my_decorator
def func_demo(request):
    return HttpResponse('func_demo')
函數視圖使用裝飾器

在類視圖中使用爲函數視圖準備的裝飾器時,不能直接添加裝飾器,須要使用method_decorator將其轉換爲適用於類視圖方法的裝飾器。測試

 

 

類視圖多繼承& Minx擴展類

使用面向對象多繼承特性,能夠經過定義父類(做爲擴展類),在父類中定義想要想類視圖補充的方法,類視圖繼承這些擴展類,即可實現代碼服用。定義父類名稱一般以Mixin結尾url

class ListModelMixin(object):
    """list擴展類"""
    def list(self, request, *args, **kwargs):
        print('查詢多條數據')


class CreateModelMixin(object):
    """create擴展類"""
    def create(self, request, *args, **kwargs):
        print('新增一條數據')


class DepartmentView(CreateModelMixin, ListModelMixin, View):
    """
    同時繼承兩個擴展類,複用list和create方法
    """
    def get(self, request):
        self.list(request)
        return HttpResponse('get page')

    def post(self, request):
        self.create(request)
        return HttpResponse('post page')
示例

 

中間件

Django中的中間件是一個輕量級、底層的插件系統,能夠介入Django的請求和響應處理過程,修改Django的輸入或輸出。中間件的設計爲開發者提供了一種無侵入式的開發方式,加強了Django框架的健壯性。咱們能夠可使用中間件,在Django處理視圖的不一樣階段對輸入或輸出進行干預。

一、定義一箇中間件,在項目中新建一個middlewares.py文件,而後在該文件中定義中間件類:

from django.utils.deprecation import MiddlewareMixin


# 定義中間件類: 經過繼承Django的MiddlewareMixin擴展類實現
class MyMiddleware(MiddlewareMixin):

    def __init__(self, get_response=None):
        # 服務器啓動,初始化中間件類時被調用,只執行一次
        super().__init__(get_response)
        print('init')

    def process_request(self, request):
        print('before 視圖')
        # 注意:能夠返回None或者response對象,若是返回response對象,則視圖函數就不會再執行了

    def process_response(self, request, response):
        print('after 視圖')
        return response
自定義中間件

二、在settings.py文件中添加中間件

 

三、定義一個視圖進行測試

def index(request):
    print('====index===')
    return HttpResponse('hello world')

 

多箇中間件的執行順序

#一、再定義一箇中間件類
 class MyMiddleware2(MiddlewareMixin):

     def __init__(self, get_response=None):
         super().__init__(get_response)
         print('init 2')

     def process_request(self, request):
         print('before 視圖 2')

     def process_response(self, request, response):
         print('after 視圖 2')
         return response

#二、註冊
 MIDDLEWARE = [
     'django.middleware.security.SecurityMiddleware',
     ...
     'middlewares.MyMiddleware',  # 註冊中間件
     'middlewares.MyMiddleware2',  
 ]

#三、執行結果
 before 視圖
 before 視圖 2
 ==index==
 after 視圖 2
 after 視圖

#四、結論
對於視圖以前執行的 process_request 方法,先 註冊的中間件先執行
對於視圖以後執行的 process_response 方法,後 註冊的中間件先執行
示例說明
相關文章
相關標籤/搜索