Django筆記二十九之中間件介紹

来源:https://www.cnblogs.com/hunterxiong/archive/2023/04/23/17347565.html
-Advertisement-
Play Games

本文首發於公眾號:Hunter後端 原文鏈接:Django筆記二十九之中間件介紹 這一節介紹一下 Django 的中間件。 關於中間件,官方文檔的解釋為:中間件是一個嵌入 Django 系統的 request 和 response 的鉤子框架,是一個能夠全局改變 Django 輸入/輸出的系統。 我 ...


本文首發於公眾號:Hunter後端
原文鏈接:Django筆記二十九之中間件介紹

這一節介紹一下 Django 的中間件。

關於中間件,官方文檔的解釋為:中間件是一個嵌入 Django 系統的 request 和 response 的鉤子框架,是一個能夠全局改變 Django 輸入/輸出的系統。

我們可以這樣理解,一個 request 請求發送到 Django 系統的過程中,在經過路由和視圖的處理前,會先經過一層處理,這個處理操作可以是日誌記錄,可以是登錄驗證甚至你想在系統里定義的功能,這個操作就是中間件實現的功能。

接下來我們將通過一個記錄請求的 ip 的功能的介紹來介紹一下中間件的實現流程。

以下是本篇筆記目錄:

  1. 請求經過 Django 然後返回的流程
  2. HttpRequest 和 HttpResponse 介紹
  3. 中間件的示例介紹
  4. 記錄訪問 ip 的功能實現

1、請求經過 Django 然後返回的流程

首先,前端發起一個請求,這個請求經由 web 伺服器轉發給 Django 系統,在進入 Django 系統後會先經過一系列的中間件的功能處理。

這個中間件會在 settings.py 里定義,Django 系統預設自帶的中間件列表如下:

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',
]

這些中間件我們也可以根據自己的需求自己定義,比如新加一個登錄許可權,或者日誌記錄,或者對輸入的參數進行格式化處理也可以,或者自己想要設置的其他功能也行,具體怎麼設置在後面介紹。

在中間件處理的流程中,請求會被按照順序從上往下處理。

這個流程過後,一個 request 請求才會被進行 URL 的路徑匹配,如果匹配上,再去找相應的 views 視圖函數進行數據處理

views 處理完之後,會形成一個 response,返回,然後再次經歷這個中間件處理,因為在每一層中間件中都類似於一種嵌套,所以返回 response 的時候,是從下往上再次處理 response 的。

中間件處理結束之後再被返回出去,給到前端。

在這整個流程處理中,可以說中間件是進行了兩次操作,一個是進入的時候處理 request,一個是返回的時候處理 response。

2、HttpRequest 和 HttpResponse 介紹

我們先來看一個視圖函數:

def time_view(request):
    now = datetime.datetime.now()
    html = "<h1>now: %s</h1>abc\nabc" % now
    return HttpResponse(html)

當 Django 接收到一個請求,系統會創建一個 HttpRequest 對象,這個對象就是上面的視圖函數里的輸入參數,request

在對數據進行處理後,系統會返回一個 HttpResponse 對象,這個就是我們 return 的內容。

在一個 HttpRequest 對象里,會包含請求的路徑、參數、請求方式、 cookie 等一切請求過來時的數據,我們可以在請求的時候根據需要存取。

在返回的 HttpResponse 中,可以是一個 html 頁面,也可以是 json 格式的數據,內容是可以自定義的,只要前端可以做相應的處理。

3、中間件的示例介紹

接下來我們定義一個中間件,結構大致如下:

# huter/middleware.py

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

    def __call__(self, request):

        # 在請求進入視圖函數前的可以執行一些操作,針對 request
        print(request.path)
        response = self.get_response(request)
        
        # 在處理完請求後,可以執行一些操作,針對 response
        # log_response_info()
        return response

然後我們在 sttings.py 里引入這個中間件,我們放到 MIDDLEWARE 列表的最下麵,說明這個中間件會在其他中間件處理完 request 之後再處理:


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',
    'hunter.middleware.TestMiddleware',
]

在 SimpleMiddleware 這個類里,call() 函數會自動調用,其中有一行,response = self.get_response(request)

在這一行函數之前,可以對請求的 request 做處理,包括我們前面說的各種功能,比如日誌、登錄驗證、參數格式化等

在這一行函數之後,獲取了 response,這個就是視圖函數返回的 HttpResponse,我們可以在這裡對它的 response.status_code 狀態碼,和 response.content 做處理

比如前面 time_view 函數返回的內容是一個 JsonResponse:

return JsonResponse({"code": 0})

那麼在這裡我們可以獲取然後處理這個 HttpResponse:


def __call__(self, request):

    response = self.get_response(request)

    content = json.loads(response.content)
    content["msg"] = "success"
    response.content = json.dumps(content)
    return response

這裡只是一個示例,因為並不是所有的 HttpResponse 都是 json 格式的數據,所以可能需要加一個 try except 做下處理

還有一個功能是我之前做過的,就是在 headers 中加一個特定的字元串,表示是我們系統專有的,用於前端判斷,這個很簡單,就是在 response 的 headers 參數中加一個鍵值對:

response.headers['system'] = 'hunter'

以上就是一個最簡單的中間件的處理方式。

process_view

除了 call 函數以外,還有一個 process_view() 的函數

這個函數是在 Django 系統調用 views 視圖函數前被調用,它的返回值是 None 或者一個 HttpResponse

如果為 None,那麼系統會接著調用視圖函數,如果是 HttpResponse 作為返回值,說明系統在這裡已經處理了請求,不需要再走views視圖函數,然後就會直接返回。

我們通過下麵的例子來解釋這個函數作用。

4、記錄訪問 ip 的功能實現

假設我們需要禁止某一個或者某一個 ip 列表的請求訪問我們的系統

當然,這個操作,在 web 伺服器那部分就可以攔截,這裡就是單純舉個例子

那麼我們這樣設置一個 process_view 的功能,在真正執行視圖函數(也就是url 匹配上的 view函數)前,取出這個 request 的訪問的ip,然後進行判斷,如果在 禁止列表,那麼則直接返回一個禁止訪問的頁面。

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


    def __call__(self, request):
        response = self.get_response(request)
        return response


    def process_view(self, request, view_func, *view_args, **view_kwargs):
        EXCLUDE_IPS = ['192.168.1.54']
        if 'HTTP_X_FORWARDED_FOR' in  request.META:
            ip =  request.META['HTTP_X_FORWARDED_FOR']
        else:
            ip = request.META['REMOTE_ADDR']
        if ip in EXCLUDE_IPS:
            return HttpResponse('<h1>您的ip被禁止</h1>')
        return None

在這裡,我們拿到請求的 ip 地址,去和我們定義的禁止ip列表做比較

如果在禁用列表,則直接返回 HttpResponse,不接著請求我們的服務來

否則,就返回 None,系統接收到 None 之後,會接著往下處理。

如果想獲取更多後端相關文章,可掃碼關註閱讀:

image


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 防抖(debounce) 一句話概括:防抖是給定一個時間周期,如果觸發事件的周期小於該事件(也就是觸發過快),則不會觸發事件。 舉個例子:我給定的時間周期是1s,如果我在觸發第一次事件後1s內觸發該事件,則重新開始計時,直到觸發周期大於1s才會執行事件的方法。 function debounce(f ...
  • 前言 數組是幾乎所有編程語言的基礎語法,JavaScript因為語法特性,之前缺少一些集合類對象,對數組的使用就會更多一些,因此我們更需要理解數組知識。 然而大部分人對數組都已經非常熟悉了,所以本文將不會介紹數組的基礎語法和用法,而是從JavaScript中數組的一些特殊之處入手,通過這些少有特性的 ...
  • 交互設計原則有很多,《小紅書的52條設計原則》可以學習下,非常棒的輸出,值得做產品設計的童鞋學習一下。 ...
  • 說明 使用 VLD 記憶體泄漏檢測工具輔助開發時整理的學習筆記。本篇介紹 VLD 源碼的編譯。同系列文章目錄可見 《記憶體泄漏檢測工具》目錄 1. VLD 庫的依賴文件 以 vld2.5.1 版本為例,下載源碼 後,源碼包中各文件的用途可看本人另一篇博客 【VLD】源碼文件概覽。使用 vld2.5.1- ...
  • 本案例實現一個test命名空間,此命名空間內有兩個函數,分別為getName()和getNameSpace(); 聲明命名空間及函數 namespace test{ const std::string& getName()和(); const std::string& getNameSpace(); ...
  • 常量指針與指針常量 #include<iostream> using namespace std; int main() { int a = 10; int b = 20; // 常量指針與指針常量 // 1.常量指針 const修飾指針 指針的指向是可以修改的(指針變數中存的地址值可以修改) 指針 ...
  • 學習Spring源碼的建議 閱讀Spring官方文檔,瞭解Spring框架的基本概念和使用方法。 下載Spring源碼,可以從官網或者GitHub上獲取。 閱讀Spring源碼的入口類,瞭解Spring框架的啟動過程和核心組件的載入順序。 閱讀Spring源碼中的註釋和文檔,瞭解每個類和方法的作用和 ...
  • 平面上有n個點(n<=100),每個點的坐標均在-10000~10000之間,其中的一些點之間有連線。 若有連線,則表示可從一個點到達另一個點,即兩點間有通路,同路的距離為兩點間的直線距離。現在的任務是找出從一點到另一點之間的最短路徑。 小提示: 兩點的距離:如果點$A$坐標為$(x_A,y_A)$ ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...