Django之中間件

一、什麼是Django中間件

    中間件是一個鉤子框架,它們可以介入Django 的請求和響應處理過程。它是一個輕量級、底層的“插件”系統,用於在全局修改Django 的輸入或輸出。每個中間件組件負責完成某個特定的功能。例如:“django.middleware.csrf.CsrfViewMiddleware”中間件的功能是防止POST跨域請求,除非在請求中帶了csrf_token纔會通過。


二、怎樣激活中間件

    我們在setting.py文件中配置中間件,在Django1.10之前叫“MIDDLEWARE_CLASSES”,從Django1.10開始就叫“MIDDLEWARE”。

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]


三、中間件執行流程

c8afc6e1aff4c4a2d05d213f8b08d6d4.png

從用戶request到response返回,每一箇中間件中可以定義五種處理函數:

process_request(self,request)
process_view(self, request, callback, callback_args, callback_kwargs)
process_template_response(self,request,response)
process_exception(self, request, exception)
process_response(self, request, response)

process_request:

    在接到用戶請求時所定義的處理函數。

process_view:

    這一步是在路由分發之後,views函數之前所執行的處理函數。

process_template_response:

    這個函數基本不用,只有當views函數返回中有render時纔會執行的處理函數。

process_exception:

    異常處理函數,只有當views中函數出現異常時纔會執行。其他process_xxx函數出現異常時,是不會觸發此函數的。

process_response:

    response返回時執行的處理函數。


一個正常的中間件執行流程:

6245c040069bfeb44eeddb3a048322b8.png

    首先,先從第一個中間件的process_request函數到達最後一箇中間件的process_request函數,如果沒有出現返回的話。緊接着又從第一個中間件的process_view函數一直執行到最後一箇中間件的process_view函數,然後將請求傳遞給views函數處理。views函數返回時,先從最後一箇中間件的process_response開始執行一直到第一個中間件的process_response函數處理完成,然後返回給用戶。

83ae8f1c94fbf2eb6dade3a65ac7cd8c.png

    從Django1.10版本開始,當某個中間件的process_request函數觸發了返回,那麼在這個中間件之後的所有中間件方法都不會執行。直接從這個中間件開始向前執行process_response函數,最終返回給用戶。

    Django1.10版本之前的版本是,當某個中間件的process_request函數觸發了返回,那麼在這個中間件之後的所有中間件的process_request方法都不會執行,但會從最後一箇中間件開始向前執行process_response函數,最終返回給用戶。


一個包含異常處理的中間件執行流程:

9b7f515a42549c856bd9a828a0573dbf.png

    process_exception函數只當views發生異常時纔會執行,它先從最後一箇中間件開始搜索異常處理方法。如果最後一箇中間件沒有處理,它會將異常傳遞給前一箇中間件,如果一直傳遞給第一個中間件都沒有處理異常。它就返回最後一箇中間件開始執行process_response函數,最終返回給用戶。

ab13337b89862b22740fde4d1f307d63.png

    如果其中某一箇中間件處理了這個異常,它就會立刻返回到最後一箇中間件開始執行process_response函數,在這個中間件之前的所有中間件的process_exception函數就不執行了。


四、如何自定義中間件

a、在項目中新建一個py文件

TestMiddleware.py

b、編輯TestMiddleware.py

from django.utils.deprecation import MiddlewareMixin

class TestMiddleware1(MiddlewareMixin):
    def process_request(self, request):
        print("Test1-->process_request")

    def process_response(self, request, response):
        print("Test1-->process_response")
        return response

    def process_view(self, request, callback, callback_args, callback_kwargs):
        print("Test1-->process_view")


class TestMiddleware2(MiddlewareMixin):
    def process_request(self, request):
        print("Test2-->process_request")

    def process_response(self, request, response):
        print("Test2-->process_response")
        return response

    def process_view(self, request, callback, callback_args, callback_kwargs):
        print("Test2-->process_view")


class TestMiddleware3(MiddlewareMixin):
    def process_request(self, request):
        print("Test3-->process_request")

    def process_response(self, request, response):
        print("Test3-->process_response")
        return response

    def process_view(self, request, callback, callback_args, callback_kwargs):
        print("Test3-->process_view")

    在Django1.10之前,我們自定義的中間件類繼承的是Object。從Django1.10開始,我們必須繼承MiddlewareMixin類。

class MiddlewareMixin(object):
    def __init__(self, get_response=None):
        self.get_response = get_response
        super(MiddlewareMixin, self).__init__()

    def __call__(self, request):
        response = None
        if hasattr(self, 'process_request'):
            response = self.process_request(request)
        if not response:
            response = self.get_response(request)
        if hasattr(self, 'process_response'):
            response = self.process_response(request, response)
        return response


c、在setting.py文件添加自定義的中間件

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'TestMiddleware.TestMiddleware1',
    'TestMiddleware.TestMiddleware2',
    'TestMiddleware.TestMiddleware3',
]

    MIDDLEWARE是一個列表,所以裏面中間件的順序是很重要的,不能隨意顛倒。爲了不影響它原先的功能,我們把自定義的中間件一般放到最後執行。當然如果你做了一個IP攔截功能的中間件,你也可以把它放到第一個執行。

    我們寫了這麼多的process_request、process_view、process_response函數,那這些都是必須要寫的的嗎?答案是否定的,你想寫哪個就寫哪個,自定義中間件中可以寫任意一個或多個函數。這些函數名是不能變的!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章