天天看點

Django 中間件

django:

  • 中間件
  • csrf
  • 緩存
  • 信号

一 、 中間件

Django的基本生命周期:

  使用者發起一次請求到url,再轉發給視圖函數,視圖函數把資料取出來再把模闆拿出來,最後進行渲染傳回給使用者

Django 中間件

Django帶有中間件的生命周期:

中間件比作是橫者的管

  請求來的是後先通過中間件,再到路由比對映射到view視圖裡,在view視圖裡的邏輯執行完了後再通過中間件傳回給使用者

Django 中間件

 每個中間件都必須繼承這個類 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
      

  

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',
    "md.hxl.HXL",    #自己寫的中間件
    "md.hxl.GYC",    #自己定制的中間件
]
      
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class LBS(MiddlewareMixin):
    def process_request(self,request):
        print("lbs-->process_request")
        #return HttpResponse("403。。。")  #如果在這裡加上return那麼将不會走到views和其他中間件,從走過的中間件的process_response傳回

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

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

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

class GYC(MiddlewareMixin):
    def process_request(self,request):
        print("gyc-->process_request")

    def process_response(self,request,response):#必須有三個參數
        """

        :param request:
        :param response: views傳回的資料
        :return: 必須傳回response
        """
        print("gyc-->process_response")
        return response

#執行的順序
#HXL-->process_request
#gyc-->process_request
#views
#gyc-->process_response
#HXL-->process_response


#直接return的順序
#lbs-->process_request
#lbs-->process_response      

如果 process_request 函數有傳回值的話就不再走其他中間件,就像csrf一樣。

Django 中間件

優化版

自定制中間件需要繼承的類

Django 中間件
Django 中間件
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class MyMiddlewareMixin(object):#自己寫一個中間件繼承的類
    def __init__(self, get_response=None):
        self.get_response = get_response
        super(MyMiddlewareMixin, self).__init__()

    def __call__(self, request):
        response = None
        if hasattr(self, 'process_request'):
            #執行目前中間件的process_request
            response = self.process_request(request)
        if not response:
            #執行下一個中間件的__call__
            response = self.get_response(request)
        if hasattr(self, 'process_response'):
            #執行目前中間件的process_response
            response = self.process_response(request, response)
        return response





class LBS(MyMiddlewareMixin):
    def process_request(self,request):
        print("lbs-->process_request")
        return HttpResponse("403。。。")  #如果在這裡加上return那麼将不會走到views和其他中間件,從走過的中間件的process_response傳回

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

class HXL(MyMiddlewareMixin):
    def process_request(self,request):
        print("HXL-->process_request")

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

class GYC(MyMiddlewareMixin):
    def process_request(self,request):
        print("gyc-->process_request")

    def process_response(self,request,response):#必須有三個參數
        """

        :param request:
        :param response: views傳回的資料
        :return: 必須傳回response
        """
        print("gyc-->process_response")
        return response      

中間件優化版

process_view(self, request, views, views_args, views_kwargs):      
Django 中間件
process_exception(self, request, exception):
      
process_exception隻對views函數有效 ,對process_vie無效      
Django 中間件
Django 中間件
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

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

    def __call__(self, request):
        response = None
        if hasattr(self, 'process_request'):
            #執行目前中間件的process_request
            response = self.process_request(request)
        if not response:
            #執行下一個中間件的__call__
            response = self.get_response(request)
        if hasattr(self, 'process_response'):
            #執行目前中間件的process_response
            response = self.process_response(request, response)
        return response





class LBS(MyMiddlewareMixin):
    def process_request(self,request):
        """
        在使用者請求時執行的函數,拿到請求
        :param request:
        :return:
        """
        print("lbs-->process_request")
        # return HttpResponse("403。。。")  #如果在這裡加上return那麼将不會走到views和其他中間件,從走過的中間件的process_response傳回
    def process_view(self, request, views_func, views_args, views_kwargs):
        """
        在執行views之前調用的函數,擷取路由上的參數
        :param request:
        :param views_func:對應的就是views的視圖函數
        :param views_args:參數清單
        :param views_kwargs:關鍵字參數
        :return:
        """
        print("lbs-->process_view")
        print(views_func, views_args, views_kwargs)


    def process_response(self,request,response):
        """
        在傳回資料時執行的函數,拿到傳回的資料
        :param request:
        :param response: views傳回的資料
        :return: 必須傳回response
        """
        print("lbs-->process_response")
        return response

    def process_exception(self, request, exception):
        """
        在異常觸發時執行的函數,拿到異常資訊
        報錯以後調用的函數,如果沒處理則到下一個異常函數處理,都沒處理則抛異常
        :param request:
        :param exception:異常資訊
        :return 如果return了就不往下走,傳回值傳回給使用者
        """
        print("lbs-->process_exception",exception)

class HXL(MyMiddlewareMixin):
    def process_request(self,request):
        print("HXL-->process_request")

    def process_view(self, request, views, views_args, views_kwargs):
        print("HXL-->process_view")


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

    def process_exception(self, request, exception):
        print("HXL-->process_exception")

class GYC(MyMiddlewareMixin):
    def process_request(self,request):
        print("gyc-->process_request")

    def process_view(self, request, views, views_args, views_kwargs):
        print("gyc-->process_view")


    def process_response(self,request,response):#必須有三個參數
        """

        :param request:
        :param response: views傳回的資料
        :return: 必須傳回response
        """
        print("gyc-->process_response")
        return response

    def process_exception(self, request, exception):
        print("gyc-->process_exception")      

View Code

Django 中間件

process_template_response(self,request,response)

Django 中間件
Django 中間件
from django.shortcuts import render,HttpResponse

# Create your views here.
class Foo:
    def __init__(self,request,html):
        self.req=request
        self.html=html
    def render(self):
        return render(self.req,self.html)

def test(request,nid):

    print("views")
    return Foo(request,"abc.html")      

傳回的對象裡有render的是後執行

Django 中間件
Django 中間件
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

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

    def __call__(self, request):
        response = None
        if hasattr(self, 'process_request'):
            #執行目前中間件的process_request
            response = self.process_request(request)
        if not response:
            #執行下一個中間件的__call__
            response = self.get_response(request)
        if hasattr(self, 'process_response'):
            #執行目前中間件的process_response
            response = self.process_response(request, response)
        return response





class LBS(MyMiddlewareMixin):
    def process_request(self,request):
        """
        在使用者請求時執行的函數,拿到請求
        :param request:
        :return:
        """
        print("lbs-->process_request")
        # return HttpResponse("403。。。")  #如果在這裡加上return那麼将不會走到views和其他中間件,從走過的中間件的process_response傳回
    def process_view(self, request, views_func, views_args, views_kwargs):
        """
        在執行views之前調用的函數,擷取路由上的參數
        :param request:
        :param views_func:對應的就是views的視圖函數
        :param views_args:參數清單
        :param views_kwargs:關鍵字參數
        :return:
        """
        print("lbs-->process_view")
        print(views_func, views_args, views_kwargs)

    def process_response(self,request,response):
        """
        在傳回資料時執行的函數,拿到傳回的資料
        :param request:
        :param response: views傳回的資料
        :return: 必須傳回response
        """
        print("lbs-->process_response")
        return response

    def process_exception(self, request, exception):
        """
        在異常觸發時執行的函數,拿到異常資訊
        報錯以後調用的函數,如果沒處理則到下一個異常函數處理,都沒處理則抛異常
        :param request:
        :param exception:異常資訊
        :return 如果return了就不往下走,傳回值傳回給使用者
        """
        print("lbs-->process_exception",exception)

    def process_template_response(self,request,response):
        """
        傳回的對象如果有render方法那麼就會執行
        :param request:請求資訊
        :param response:傳回的對象
        :return:
        """
        print("lbs-->process_template_response")
        return response

class HXL(MyMiddlewareMixin):
    def process_request(self,request):
        print("HXL-->process_request")

    def process_view(self, request, views, views_args, views_kwargs):
        print("HXL-->process_view")


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

    def process_exception(self, request, exception):
        print("HXL-->process_exception")

    def process_template_response(self,request,response):
        print("HXL-->process_template_response")
        return response

class GYC(MyMiddlewareMixin):
    def process_request(self,request):
        print("gyc-->process_request")

    def process_view(self, request, views, views_args, views_kwargs):
        print("gyc-->process_view")


    def process_response(self,request,response):#必須有三個參數
        """

        :param request:
        :param response: views傳回的資料
        :return: 必須傳回response
        """
        print("gyc-->process_response")
        return response

    def process_exception(self, request, exception):
        print("gyc-->process_exception")

    def process_template_response(self,request,response):
        print("gyc-->process_template_response")
        return response      

process_template_response

中間件中可以定義四個方法,分别是:

  • process_request(self,request)    #在請求到了之前就已經執行了,比如csrf,請求頭的過濾
  • process_view(self, request, callback, callback_args, callback_kwargs)    
  • process_template_response(self,request,response)    #在views結束後時執行的
  • process_exception(self, request, exception)
  • process_response(self, request, response)
上一篇: PIL子產品