django框架之中間件

中間件簡介

django 中的中間件(middleware),在django中,中間件其實就是一個類,在請求到來和結束後,django會根據本身的規則在合適的時機執行中間件中相應的方法。html

在django項目的settings模塊中,有一個 MIDDLEWARE_CLASSES 變量,其中每個元素就是一箇中間件python

如圖:web

中間件中一共有五個方法:django

process_requestjson

process_view框架

process_exception函數

process_responsepost

process_template_responseurl

一、中間件之process_request,process_response

process_request(self,request)spa

process_response(self, request, response)

當用戶發起請求的時候會依次通過全部的的中間件,這個時候的請求時process_request,最後到達views的函數中,views函數處理後,在依次穿過中間件,這個時候是process_response,最後返回給請求者

在django中叫中間件,在其餘web框架中,有的叫管道,httphandle

上述截圖中的中間件都是django中的,咱們也能夠本身定義一箇中間件,咱們能夠本身寫一個類,可是必須繼承MiddlewareMixin

因此須要導入:from django.utils.deprecation import MiddlewareMixin

咱們在項目文件下建立一個Middle目錄,並在下面建立md.py代碼例子以下:

django項目的settings模塊

md.py

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect,render,HttpResponse
class M1(MiddlewareMixin):
    def process_request(self,request):
        print("M1.process_request")
    def process_response(self,request,response):
        print("m1.process_response")
        return response
class M2(MiddlewareMixin):
    def process_request(self,request):
        print("M2.process_request")

    def process_response(self, request, response):
        print("m2.process_response")
        return response
# 執行結果是:
#         M1.process_request
#         M2.process_request
#         m2.process_response
#         m1.process_response

views.py

from django.shortcuts import render,HttpResponse,redirect
from django.forms import Form
from django.forms import fields
from django.forms import widgets

def test(request):
    print("test")
    return HttpResponse("xuyuanyuan")

url.py

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^test.html$', views.test),

]

 

當頁面發起請求時:

pycharm上面顯示的運行結果是:

可是若是當請求到達請求2的時候直接不符合條件返回,程序將把請求直接發給中間件2返回,而後依次返回到請求者

用以下圖進行理解:

固然這是在django1.10的時候,在以前的版本的時候是直接返回到最後一箇中間件的response,而後向上依次返回,最後到發起請求

示例:

md.py

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect,render,HttpResponse

class M1(MiddlewareMixin):
    def process_request(self,request):
        print("M1.process_request")
    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("M1.process_view")

    def process_response(self,request,response):
        print("m1.process_response")
        return response


class M2(MiddlewareMixin):
    def process_request(self,request):
        print("M2.process_request")
        return M2.process_request
    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("M2.process_view")
        # response=callback(request,*callback_args,**callback_kwargs)
        # return response
    def process_response(self,request,response):
        print("m2.process_response")
        # return response


class M3(MiddlewareMixin):
    def process_request(self, request):
        print("M3.process_request")

    def process_view(self, request, callback, callback_args, callback_kwargs):
        print("M3.process_view")

    def process_response(self, request, response):
        print("m3.process_response")
        return response

執行結果是:

解釋說明:

# 執行結果是:(  在django如今的版本中,由於在m2中 def process_request(self,request):
#         print("M2.process_request")
#         return M2.process_request有返回值,故而遇到返回值就直接找到本身的response返回)
# M1.process_request
# M2.process_request
# m2.process_response
# m1.process_response
# (  在django之前的版本,由於在m2中 def process_request(self,request):
#         print("M2.process_request")
#         return M2.process_request有返回值,故而遇到返回值就直接找到最後的一個response返回,
# 故而執行結果會變成:
# M1.process_request
# M2.process_request
# m3.process_response
# m2.process_response
# m1.process_response)

二、中間件之process_view

process_view(self, request, callback, callback_args, callback_kwargs)

咱們在md.py文件中的的代碼進行更改:

示例一:

md.py

class M1(MiddlewareMixin):
    def process_request(self,request):
        print("M1.process_request")
    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("M1.process_view")
        # response=callback(request,*callback_args,**callback_kwargs)
        # return response
    def process_response(self,request,response):
        print("m1.process_response")
        return response

class M2(MiddlewareMixin):
    def process_request(self,request):
        print("M2.process_request")
    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("M2.process_view")
        response=callback(request,*callback_args,**callback_kwargs)
        return response
    def process_response(self,request,response):
        print("m2.process_response")
        return response
# 執行結果是:
#         M1.process_request
#         M2.process_request
#         M1.process_view
#         M2.process_view
#         test
#         m2.process_response
#         m1.process_response

示例二:

class M1(MiddlewareMixin):
    def process_request(self,request):
        print("M1.process_request")
    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("M1.process_view")
        response=callback(request,*callback_args,**callback_kwargs)
        return response
    def process_response(self,request,response):
        print("m1.process_response")
        return response

class M2(MiddlewareMixin):
    def process_request(self,request):
        print("M2.process_request")
    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("M2.process_view")
        response=callback(request,*callback_args,**callback_kwargs)
        return response
    def process_response(self,request,response):
        print("m2.process_response")
        return response

# 執行結果是:
#         M1.process_request
#         M2.process_request
#         M1.process_view
#         test
#         m2.process_response
#         m1.process_response

關係以下圖示例:

當最後一箇中間的process_request到達路由關係映射以後,返回到中間件1的process_view,而後依次往下,到達views函數,最後經過process_response依次返回到達用戶

三、中間件之process_exception

process_exception(self, request, exception)

當views的函數中出現錯誤時,就會執行process_exception方法

示例:

class M1(MiddlewareMixin):
    def process_request(self,request):
        print("M1.process_request")
    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("M1.process_view")
        # response=callback(request,*callback_args,**callback_kwargs)
        # return response
    def process_response(self,request,response):
        print("m1.process_response")
        return response
    def process_exception(self,request,exception):
        print("M1.process_exception")

class M2(MiddlewareMixin):
    def process_request(self,request):
        print("M2.process_request")
    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("M2.process_view")
        # response=callback(request,*callback_args,**callback_kwargs)
        # return response
    def process_response(self,request,response):
        print("m2.process_response")
        return response
    def process_exception(self,request,exception):
        print("M2.process_exception")
        return HttpResponse("異常處理")
# 執行結果是:
        # M1.process_request
        # M2.process_request
        # M1.process_view
        # M2.process_view
        # M2.process_exception
        # m2.process_response
        # m1.process_response

  

若是在中間中添加了process_exception方法,工做圖示爲:

這樣當用戶發起請求的時候到達中間件3的process_request以後會到達urls路由關係映射這裏,若是匹配到了就會到中間件1的process_view,而後依次傳遞到中間件3的process_view,到達view函數。若是view函數中有報錯,則會從中間件3依次向上判斷每一箇中間件的process_exception是否能匹配到這個錯誤信息,若是匹配到則直接返回到最後一箇中間件,這裏即中間件3的process_response,而後依次返回到用戶,若是沒有匹配到這個錯誤則直接在頁面顯示錯誤信息。若是view函數中沒有錯誤,則到中間3即最後一箇中間件3的process_response,而後依次向上,傳到用戶

四、中間件之process_template_responseprocess

process_template_response(self,request,response)

只有當views函數中返回的對象中具備render方法,是就會直接process_template_responseprocess

示例一:

 views.py

from django.shortcuts import render,HttpResponse,redirect
from django.forms import Form
from django.forms import fields
# =======在函數中添加render,使md.py文件裏的def process_template_response函數執行
class JSONResponse:
    def __init__(self,req,status,msg):
        self.req=req
        self.status=status
        self.msg=msg
    def render(self):
        import json
        ret={
            "status":self.status,
            "msg":self.msg
        }
        return HttpResponse(json.dump(ret))

def test(request):
    ret={}
    return JSONResponse(request,True,"哈哈哈哈,錯了吧")

md.py

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect,render,HttpResponse
class M1(MiddlewareMixin):
    def process_request(self,request):
        print("M1.process_request")
    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("M1.process_view")

    def process_response(self,request,response):
        print("m1.process_response")
        return response
    def process_exception(self,request,exception):
        print("M1.process_exception")

    def process_template_response(self,request,response):
        """
        若是視圖函數的返回值中,有render方法,則會執行該函數
        :param request:
        :param response:
        :return:
        """
        print("M1.process_template_response")
        return response

class M2(MiddlewareMixin):
    def process_request(self,request):
        print("M2.process_request")
    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("M2.process_view")
        # response=callback(request,*callback_args,**callback_kwargs)
        # return response
    def process_response(self,request,response):
        print("m2.process_response")
        return response
    def process_exception(self,request,exception):
        print("M2.process_exception")
        return HttpResponse("異常處理")
    def process_template_response(self,request,response):
        """
        若是視圖函數的返回值中,有render方法,則會執行該函數
        :param request:
        :param response:
        :return:
        """
        print("M2.process_template_response")
        return response
# 執行結果是:在頁面顯示「異常處理」,
#     def process_exception(self,request,exception):
#         print("M1.process_exception")該函數未執行,因爲
#         def process_exception(self, request, exception):
#             print("M2.process_exception")
#             return HttpResponse("異常處理")
        # 在M2中有return返回值
# 終端上的執行結果是:
#         M1.process_request
#         M2.process_request
#         M1.process_view
#         M2.process_view
#         M2.process_template_response
#         M1.process_template_response
#         M2.process_exception
#         m2.process_response
#         m1.process_response

頁面上的結果爲:

後臺顯示:

示例二:

views.py

from django.shortcuts import render,HttpResponse,redirect
from django.forms import Form
from django.forms import fields
from django.forms import widgets


# =======在函數中添加render,使md.py文件裏的def process_template_response函數執行
class JSONResponse:
    def __init__(self,req,status,msg):
        self.req=req
        self.status=status
        self.msg=msg
    def render(self):
        import json
        ret={
            "status":self.status,
            "msg":self.msg
        }
        return HttpResponse(json.dump(ret))

def test(request):
    ret={}
    return JSONResponse(request,True,"哈哈哈哈,錯了吧")

 md.py

class M1(MiddlewareMixin):
    def process_request(self,request):
        print("M1.process_request")

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("M1.process_view")

    def process_response(self,request,response):
        print("m1.process_response")
        return response
    def process_exception(self,request,exception):
        print("M1.process_exception")
        return HttpResponse("異常處理")
    def process_template_response(self,request,response):
        """
        若是視圖函數的返回值中,有render方法,則會執行該函數
        :param request:
        :param response:
        :return:
        """
        print("M1.process_template_response")
        return response

class M2(MiddlewareMixin):
    def process_request(self,request):
        print("M2.process_request")
    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("M2.process_view")
        # response=callback(request,*callback_args,**callback_kwargs)
        # return response
    def process_response(self,request,response):
        print("m2.process_response")
        # return response
    def process_exception(self,request,exception):
        print("M2.process_exception")

    def process_template_response(self,request,response):
        """
        若是視圖函數的返回值中,有render方法,則會執行該函數
        :param request:
        :param response:
        :return:
        """
        print("M2.process_template_response")
        return response
# 執行結果是:在頁面顯示「異常處理」,全部的函數都執行了
# 終端上的執行結果是:
#         M1.process_request
#         M2.process_request
#         M1.process_view
#         M2.process_view
#         M2.process_template_response
#         M1.process_template_response
#         M2.process_exception
#         M1.process_exception
#         m2.process_response
#         m1.process_response

相關文章
相關標籤/搜索