天天看點

django 中間件詳解以及測試代碼

django中間件,在http請求 到達視圖函數之前 和視圖函數return之後,django會根據自己的規則在合适的時機執行中間件中相應的方法。

看圖了解中間件

django 中間件詳解以及測試代碼

django中間件的執行順序如上圖示

無論是在請求到達view視圖之前還是在response傳回給使用者之前,我們都可以進行攔截到,然後做自己的處理然後在給view處理,或者傳回給使用者。

這裡介紹django中間件可以定義的五種方法:

1.process_request(self,request) 2.process_view(self, request, callback, callback_args, callback_kwargs) 3.process_template_response(self,request,response) 4.process_exception(self, request, exception) 5.process_response(self, request, response)

1.process_request(self,request)方法

這個方法是執行在request請求到達view視圖之前,它可以攔截下來,将使用者的headers、body、meta已經使用者要請求的路由等等後可以攔截到,然後處理自己需要的邏輯。

應用:

1、可以在這裡列印日志,将使用者請求的路由、攜帶的headers、傳來的body、GET參數等全部列印到日志裡面

2、可以在這裡判斷使用者是否有權限進入這個路由,沒有權限就可以将使用者跳轉到其他路由。

def process_request(self,request):
     print('===============================================')
     print('攔截請求的位址:',request.path)
     request_dic = json.loads(request.body, encoding='utf-8')
     print(request_dic)
           

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

(1)執行完所有中間件的request方法‘

(2)url比對成功

(3)拿到 視圖函數的名稱、參數,(注意不執行) 再執行process_view()方法

(4)最後去執行視圖函數

這個方法發生在已經走過路由,即将到達vie視圖函數。

可以拿到view視圖函數,這裡的用法筆者目前也沒有用到,後續用到再次追加。

3.process_template_response(self,request,response)

這個方法,隻有在視圖函數的傳回對象中有render方法才會執行!

并把對象的render方法的傳回值傳回給使用者(注意不傳回視圖函數的return的結果了,而是傳回視圖函數 return值(對象)的render方法)

同樣,這裡的用法筆者目前也沒有用到,後續用到再次追加。

4.process_exception(self, request, exception)

這個方法在view視圖裡面出現未知的錯誤時會執行,

應用:

在view視圖函數出現未知的錯誤時,将使用者重定向到其他頁面,防止使用者界面出現錯誤導緻的使用者體驗下降。

def process_exception(self,request,exception):
        print('發生錯誤的請求位址',request.path,exception.__str__)
        return render(request,'Home.html')
           

5.process_response(self, request, response)

這個方法,執行在response傳回給使用者之前,開發者可以在這裡将需要修改的response内容修改後,再次傳回給使用者。

應用:

例如筆者遇到需要處理使用者的翻譯問題,那麼不可能在每個view視圖函數裡面再意義一一翻譯,這樣肯定是不可取的。那麼就可以在這裡response到達使用者之前,判斷語言環境之後将翻譯處理好,然後傳回給使用者。

def process_response(self,request,response):
        if request.META.get('HTTP_LANGUAGE') == 'en':
            translation_file_path = os.path.dirname(os.path.abspath(__file__)) + '/translation_file.txt'
            with open(translation_file_path,'r') as f:
                trans_list = f.read().split('\n')
                dic = json.loads(response.content, encoding='utf-8')
                for item in trans_list:
                    if dic['message'] in item:
                        item_tran_list = item.split(';')
                        dic['message'] = item_tran_list[]
                f.close()
            response.content = json.dumps(dic)
        return response
           

最後放上筆者圖檔中使用到的中間件整體代碼

from django.http import HttpResponse
import json,os
# 繼承自一個檔案
from django.shortcuts import render
from django.utils.deprecation import MiddlewareMixin
# 注意寫完之後要在setings裡面進行注冊 在MIDDLEARE裡面注冊使用
class myMiddle(MiddlewareMixin):
    def process_request(self,request):
        print('===========================================')
        print('攔截請求的位址:',request.path)
        request_dic = json.loads(request.body, encoding='utf-8')
        print(request_dic)

    def process_exception(self,request,exception):
        print('發生錯誤的請求位址',request.path,exception.__str__)
        return render(request,'Home.html')

    def process_response(self,request,response):
        response_dic = json.loads(response.content,encoding='utf-8')
        print(response_dic)
        return response