以函數的方式定義的視圖成爲函數視圖,函數視圖便於理解。可是遇到一個視圖對應的路徑提供了多種不一樣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')
路由那裏,我則須要使用該視圖的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將其轉換爲適用於類視圖方法的裝飾器。測試
使用面向對象多繼承特性,能夠經過定義父類(做爲擴展類),在父類中定義想要想類視圖補充的方法,類視圖繼承這些擴展類,即可實現代碼服用。定義父類名稱一般以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 方法,後 註冊的中間件先執行