1. 程式人生 > >Django 詳解 中間件Middleware

Django 詳解 中間件Middleware

精確 一次 pri 是什麽 elf ret pytho dmi .py

Django中間件

還是涉及到django的請求生命周期。middle ware 請求穿過中間件到達url,再經過中間件返回給用戶。

簡單實例

django項目根目錄新建一個Middle文件夾,再新建一個test.py文件

技術分享圖片

在test文件中寫入;其中的類必須繼承 from django.utils.deprecation import MiddlewareMixin

from django.utils.deprecation import MiddlewareMixin
class M1(MiddlewareMixin):
    def process_request(self, request):
        
print(m1) def process_response(self, request, response): print(m1_r) return response class M2(MiddlewareMixin): def process_request(self, request): print(m2) def process_response(self, request, response): print(m2_r) return response class
M3(MiddlewareMixin): def process_request(self, request): print(m3) def process_response(self, request, response): print(m3_r) return response

將你的測試中間件加入Django的中間件配置中,settings文件

技術分享圖片

隨便建一組對應路由。

技術分享圖片

在index函數裏面寫上

def index(request):
    print(‘到達‘)
    return HttpResponse(‘ok‘)

查看結果:

技術分享圖片

此時如果給某個中間件的process_request返回一個HttpResponse:

#!/user/bin/env python
# -*-coding: utf-8-*-
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class M1(MiddlewareMixin):
    def process_request(self, request):
        print(‘m1‘)
    def process_response(self, request, response):
        print(‘m1_r‘)
        return response


class M2(MiddlewareMixin):
    def process_request(self, request):
        print(‘m2‘)
        return HttpResponse(‘中斷‘)  # 這裏返回
    def process_response(self, request, response):
        print(‘m2_r‘)
        return response


class M3(MiddlewareMixin):
    def process_request(self, request):
        print(‘m3‘)

    def process_response(self, request, response):
        print(‘m3_r‘)
        return response

查看下結果

技術分享圖片

技術分享圖片

技術分享圖片

可能你好像懂了,但是並沒有,真正的中間件過程其實還有一個process_view.

技術分享圖片View Code

技術分享圖片

技術分享圖片

自定制中間件的另一種方式

下面是最新的django2.1文檔內的自定制中間件的另一種寫法。

一個中間件工廠是可以被調用的,它接收一個可調用的get_response方法並返回一個中間件。中間件也是可調用的,它接收請求並返回響應,就像一個view視圖

def simple_middleware(get_response):
    # 一次性配置和初始化

    def middleware(request):
        # 在每個請求之前被執行的代碼
        #這個視圖(和後面的中間件)被調用

        response = get_response(request)

        # 在每個請求或者響應之後代碼被執行
        # the view is called.

        return response

    return middleware

或者他也可以被重寫成一個實例可以被調用的類,像這個:

class SimpleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # 一次性配置和初始化

    def __call__(self, request):
        # 在每一次請求之前代碼被執行
        # 視圖或者接下來的中間件被調用
        response = self.get_response(request)

        # 在每個請求或者響應之後代碼將會被執行
        # the view is called.

        return response

可調用的get_response是由django提供的,可以是真實的視圖函數或者也可以是鏈上的下一個中間件。當前的中間件不需要具體精確地知道或者關心它是什麽,只是它代表接下來執行(到來的)是什麽。

上面是一個小小的簡化,可調用的get_response如果在中間件的最後一位,將不會是一個真實的視圖函數,更可能是處理的一個外部包裝方法,它關註於應用視圖中間件,調用視圖和合適的URL參數,並且使用template和exception中間件.

中間件可以生存在你的Python路徑的任何地方。

__init__(get_response)

中間件工廠必須接收一個get_response參數,你也可以為中間件初始化一些全局的狀態。記住下面的這幾點

1、django只能使用get_response參數來初始化你的中間件,所以你不能定義__init__()來需要其他的參數

2、跟__call__()方法每次請求被調用不同,__init__()方法只會被調用一次,當web服務啟動的時候

例如

class LoginMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    @method_decorator(adminlogin)
    def __call__(self, request):
        if request.method == "PUT":
            request.data = dict(urllib.parse.parse_qsl(request.body.decode()))
            request.data.update(request.GET.dict())
        elif request.method == "POST":
            request.data = request.POST.copy().dict()
        response = self.get_response(request)
        return response

詳情請查閱django(version2.1)文檔:https://docs.djangoproject.com/en/2.1/topics/http/middleware/

Django 詳解 中間件Middleware