1. 程式人生 > >Django 之 中間件

Django 之 中間件

一個 sessions proc quest except mixin span 級別 都是

一、概念

1、什麽是中間件?

  官方解釋:中間件是用來處理Django的請求和響應的框架級別的鉤子。基於全局範圍產生影響。

  平民解釋:中間件是幫助我們在視圖函數執行前和執行後做的操作。它本質上就是一個自定義類,類中定義了幾個方法,Django框架會在處理請求的特定的時間去執行這些方法。其余request請求,終於response請求。

2、中間件在Django項目中Settings.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, ]

  MIDDLEWARE配置項是一個列表,列表中是一個個字符串,這些字符串其實是一個一個的類,也就是一個一個的中間件。

3、自定義中間件

  1、中間件可以定義五個方法,分別是:

    1、process_request(self,request) 處理請求的方法

    2、process_view(self,request,view_func,view_args,view_kwargs) 處理視圖的方法

    3、process_template_response(self,request,response)  處理模板的方法

    4、process_exception(self,request,exception)  處理異常的方法

    5、process_response(self,request,response)  處理響應的方法

  以上方法的返回值可以使None,或者是HttpResponse對象,如果是None,就按照自定義的中間件的方法繼續向下執行,直到process_response方法執行結束,如果是HttpResponse對象,就直接將這個對象返回給用戶。

二、五種自定義中間件

  1、process_request

  自定義一個中間件的示例

    1、在APP下創建一個py文件,在py文件中定義中間件

from django.utils.deprecation import MiddlewareMixin


class MD1(MiddlewareMixin):

    def process_request(self, request):            #  process_request方法 
        print("MD1裏面的 process_request")      # 此時沒有返回值 依次向下執行

    def process_response(self, request, response):       # process_response方法
        print("MD1裏面的 process_response")
        return response
class MD2(MiddlewareMixin):

    def process_request(self, request):            #  process_request方法 
        print("MD2裏面的 process_request")      # 此時沒有返回值 依次向下執行

    def process_response(self, request, response):       # process_response方法
        print("MD2裏面的 process_response")
        return response

    2、需要在setting.py中的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,
    middlewares.MD1,  # 自定義中間件MD1
    middlewares.MD2  # 自定義中間件MD2
]

    3、當瀏覽器發送了請求之後,Django服務器響應請求,返回給瀏覽器。此時終端打印出如下內容:

MD1裏面的 process_request
MD2裏面的 process_request
app01 中的 index視圖

    4、如果把MD1he MD2在setting.py中的順序調換一下,打印內容就是如下:

MD2裏面的 process_request
MD1裏面的 process_request
app01 中的 index視圖

    因此,process_request的執行順序是按照註冊順序執行的。且是在視圖函數執行前執行的。

    5、總結:

      1、中間件的process_request方法是在執行視圖函數之前執行的。

      2、當配置多個中間件時,會按照MIDDLEWARE中的註冊順序,從上到下依次執行。

      3、不同中間件之間傳遞的request都是同一個對象。從請求開始到響應結束,request都是同一個對象。

      4、如果內部有返回 HttpResponse對象,則不去執行視圖函數,而是直接跳過所有的中間環節,執行process_response方法,以及其前邊的方法。

  2、process_response

    1、示例

  

from django.utils.deprecation import MiddlewareMixin


class MD1(MiddlewareMixin):     # 中間件MD1

    def process_request(self, request):           # process_response方法
        print("MD1裏面的 process_request")

    def process_response(self, request, response):
        print("MD1裏面的 process_response")
        return response


class MD2(MiddlewareMixin):     # 中間件MD2
    def process_request(self, request):
        print("MD2裏面的 process_request")

    def process_response(self, request, response):
        print("MD2裏面的 process_response")
        return response

# 每個類都是一個中間件

    2、process_response(self,request,response)有兩個參數,request就是一個請求對象,response是視圖函數放給的HttpResponse對象。該方法的返回值,也就是直接在中間件中寫的返回值也必須是HttpResponse對象。

    3、訪問視圖函數,即匹配URL之後,執行視圖函數。打印如下內容

MD2裏面的 process_request
MD1裏面的 process_request
app01 中的 index視圖
MD1裏面的 process_response
MD2裏面的 process_response

    如圖所示:process_response方法是在視圖函數執行之後,執行的。並且當有多個process_response方法時,按照 註冊順序的倒敘執行。

  3、process_view

    1、處理視圖的函數

      process_view(self,request,view_func,view_args,view_kwargs)

      該方法有四個參數

      1.request是HttpRequest對象

      2.view_func 是Django使用的視圖函數。(它是實際的函數對象,而不是一個單純的函數名字)。

      3.view_args是傳遞給視圖函數的位置參數的元祖

      4.view_kwargs是傳遞給視圖函數的關鍵字參數的字典

    2、Django會在調用視圖函數前調用process_view方法。

      他可以返回None或HttpResponse對象。如果返回None,繼續向下執行,如果返回HttpResponse對象,將不再繼續向下執行其他中間件中的process_view方法,而是直接執行process_response方法。

    3、示例

from django.utils.deprecation import MiddlewareMixin


class MD1(MiddlewareMixin):

    def process_request(self, request):        # resquest 方法
        print("MD1裏面的 process_request")

    def process_response(self, request, response):     # response 方法
        print("MD1裏面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):   # view方法
        print("-" * 80)
        print("MD1 中的process_view")
        print(view_func, view_func.__name__)


class MD2(MiddlewareMixin):
    def process_request(self, request):
        print("MD2裏面的 process_request")

    def process_response(self, request, response):
        print("MD2裏面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD2 中的process_view")
        print(view_func, view_func.__name__)

    輸出結果

MD2裏面的 process_request
MD1裏面的 process_request
--------------------------------------------------------------------------------
MD2 中的process_view
<function index at 0x000001DE68317488> index
--------------------------------------------------------------------------------
MD1 中的process_view
<function index at 0x000001DE68317488> index
app01 中的 index視圖
MD1裏面的 process_response
MD2裏面的 process_response

    由圖可知:process_view方法是在process_request之後,視圖函數之前,並且按照註冊順序的正序執行。

  4、process_exception

    1、處理異常的方法

    2、參數

    process_exception(self,request,exception)

      1、HttpRequest對象

      2、視圖函數異常時產生的Exception對象

    3、只有當視圖函數異常時才會執行。如果返回只是None,就繼續向下執行,如果返回值是一個HttpResponse對象,則不再繼續向下執行其他的中間件的process_exception方法,而是直接執行process_response方法。且如果有多個中間件的時候,按照註冊順序的倒敘執行。

    4、示例

from django.utils.deprecation import MiddlewareMixin


class MD1(MiddlewareMixin):

    def process_request(self, request):
        print("MD1裏面的 process_request")

    def process_response(self, request, response):
        print("MD1裏面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD1 中的process_view")
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(exception)
        print("MD1 中的process_exception")


class MD2(MiddlewareMixin):
    def process_request(self, request):
        print("MD2裏面的 process_request")

    def process_response(self, request, response):
        print("MD2裏面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD2 中的process_view")
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(exception)
        print("MD2 中的process_exception")

    打印結果

MD2裏面的 process_request
MD1裏面的 process_request
--------------------------------------------------------------------------------
MD2 中的process_view
<function index at 0x0000022C09727488> index
--------------------------------------------------------------------------------
MD1 中的process_view
<function index at 0x0000022C09727488> index
app01 中的 index視圖
呵呵
MD1 中的process_exception
MD1裏面的 process_response
MD2裏面的 process_response

    註意,這裏沒有執行MD2中的process_exception方法,因為MD1中的process_exception方法已經返回了響應對象。

   5、process_template_response

    1、參數:

        process_template_response(self,request,response)

        一個是HttpRequest對象,response是一個TemplateResponse對象。

    2、process_template_response是在視圖函數執行完成之後立即執行的,但是前提條件是,視圖函數返回的對象有一個render()方法

    3、示例

class MD1(MiddlewareMixin):

    def process_request(self, request):
        print("MD1裏面的 process_request")

    def process_response(self, request, response):
        print("MD1裏面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD1 中的process_view")
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(exception)
        print("MD1 中的process_exception")
        return HttpResponse(str(exception))

    def process_template_response(self, request, response):
        print("MD1 中的process_template_response")
        return response


class MD2(MiddlewareMixin):
    def process_request(self, request):
        print("MD2裏面的 process_request")

    def process_response(self, request, response):
        print("MD2裏面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD2 中的process_view")
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(exception)
        print("MD2 中的process_exception")

    def process_template_response(self, request, response):
        print("MD2 中的process_template_response")
        return response

     views.py中

def index(request):
    print("app01 中的 index視圖")

    def render():
        print("in index/render")
        return HttpResponse("O98K")
    rep = HttpResponse("OK")
    rep.render = render
    return rep

    4、輸出結果

MD2裏面的 process_request
MD1裏面的 process_request
--------------------------------------------------------------------------------
MD2 中的process_view
<function index at 0x000001C111B97488> index
--------------------------------------------------------------------------------
MD1 中的process_view
<function index at 0x000001C111B97488> index
app01 中的 index視圖
MD1 中的process_template_response
MD2 中的process_template_response
in index/render
MD1裏面的 process_response
MD2裏面的 process_response

    試圖執行完成之後,立即執行process_template_response方法,順序是倒敘執行。先執行MD1,再執行MD2,接著執行視圖函數的HttpResponse對象的render方法,返回一個新的HttpResponse對象,接著執行中間件的process_response方法。

Django 之 中間件