請求(一)Django Ninja 處理 HTTP 請求
文章目錄
2024 iThome 鐵人賽
這是 Django Ninja 系列教學的第 9 篇。
歡迎來到第三章第二節!
作為 API 的核心邏輯實現,view 函式無疑是 Django Ninja API 的靈魂所在。
Django Ninja 和 FastAPI、Flask 一樣,主要是採用 function-based views(以下簡稱 FBVs)。所以它的學習重點,幾乎都繞圍在 view 函式的 input 和 output。
換句話說,整個 Django Ninja 框架的能力,構成了 view 函式的這些關鍵部分,包括但不限於:
- 處理 HTTP 請求的參數與 body。
- 處理 HTTP 回應內容的序列化與格式化。
- 資料驗證與錯誤處理。
它們共同構成了 Django Ninja 的主要功能。
本節和下一節,將集中討論上述 3 點中的前兩點——請求與回應。至於第三點,將留到第五章再行介紹。
本節導覽
繼上一節的「路由」後,本節將探討 Django Ninja 如何處理 HTTP 請求——如何解析 path、URL 查詢參數和 body。
本節一共有 4 篇:
- 卷 9:請求(一)Django Ninja 處理 HTTP 請求(本文)
- 卷 10:請求(二)路徑參數 - Path Parameters
- 卷 11:請求(三)查詢參數 - Query Parameters
- 卷 12:請求(四)Request Body 與 Schema 介紹
此外,因為 view 函式處理請求功能,已涉及 Django Ninja 如何使用 type hints 來驗證請求資料。我們的範例程式碼會開始加上 Python 型別提示。
Type hints 的語法以 Python 3.12 為準。
官方文件
本系列的寫作不時會參考「Django Ninja 官方文件」,尤其是架構的呈現。
但文件畢竟是給全體開發者看的,並沒有充分考慮到學習的順序。
而本列系主要面向入門者,所以我們會更加注重實際操作與入門者的需求,並適時補充一些背景知識,確保學習曲線能相對平緩。
此外,就框架本身,我們也會提供更多實例和解釋,讓新概念更好理解和掌握。
但無論如何,官方文件仍是你在使用 Django Ninja 時,需要時時參考的內容——雖然它寫得比 Django 或 Django REST framework 的文件,相對「簡單」很多!
本文主旨
本文作為第二節的概論,目標是讓你對 Django Ninja 的 view 函式與它如何處理 HTTP 請求有基本的認識。
我們將透過以下三個重點來讓你逐步熟悉:
- FBVs 的優點。
- Django Ninja 對 HTTP 請求的處理流程。
- Django Ninja 與 Type Hints 的緊密結合。
話不說多,我們直接開始。
Class-based views (CBVs) 和 FBVs 都是實現 Django MTV 架構 中的 Views 手段,各有其適用場景。
CBVs 有重用程式碼優勢,適合大型專案。而 FBVs 則以簡單、直接為賣點,方便快速開發中小型專案。
兩者的比較,可參考這篇〈Day27 : CBV vs. FBV〉。
因為 Django Ninja 採 FBVs,本文只探討 FBVs 的優點。
一、FBV 的優點
FBVs 是 Django Ninja 採用的 view 形式。與 CBVs 相比,FBVs 更加簡潔、靈活,能夠讓開發者輕鬆編寫出 API 邏輯而不需要了解太多背景知識,比如「如何正確覆寫某個 CBV 屬性」。
簡潔與靈活
FBVs 不需要繼承或覆寫類別方法,所有的邏輯都集中在一個函式中。
這使得寫作和維護程式碼更加直觀。
由於 FBVs 本質是個函式,它可以更靈活地應用各種邏輯和條件,開發者能在單一函式中完全控制整個請求的處理流程,而不需要考慮類別的結構或繼承關係。
容易 Debug
FBVs 的程式碼相對直觀,對於初學者來說,閱讀、理解起來更加容易。發生錯誤時,你可以快速定位問題,這是 CBVs 不易達到的便利性。
我的看法
Django 是個功能全面的框架,但也常被批評為「笨重」。FBVs 在一定程度上緩解了這種笨重感。
試想,一個剛接觸 Django 的新手,在理解完各種框架的環境設定後,還要深入 CBVs 的世界,是否太過沉重?
總之,如果你問我,我絕對更偏好 FBVs——而且「輕量化」是現代開發的趨勢。
二、Django Ninja 對 HTTP 請求的處理流程
Django Ninja 對「請求」的處理可以分為幾個關鍵步驟:
- 路由配對:當請求進來時,框架首先會將來源 URL 與定義的路徑規則(端點)進行配對。若配對成功,則將 HTTP 請求與相關參數傳遞給 view 函式。
- 參數解析:從 URL 中提取路徑參數(path parameters)和查詢參數(query parameters),將它們轉換為 view 函式的「引數」(arguments)。根據函式的 type hints 自動進行型別轉換和驗證。
- Request body 處理:對於 POST 或 PUT 等帶有 body 的請求,Django Ninja 讓開發者使用 Schema(Pydantic BaseModel)定義 body 資料模型,並自動將傳入的資料對應到這些模型。
Django Ninja 處理 HTTP 請求流程
上述第 1 點已在本章第一節詳細解說。
第 2 和第 3 點則是本節共 4 篇文章的主要內容。
三、Django Ninja 與 Type Hints 的緊密結合
Django Ninja 非常依賴 Python 的 type hints 來處理 HTTP 請求中的資料。
並透過 Pydantic 實現了自動資料驗證和類別轉換,減少了開發者手動檢查和轉換資料的負擔。
例如以下程式碼:
1 |
|
當post_id
參數被標記為int
時,Django Ninja 會進行型別檢查。如果傳入的參數無法轉換為int
,框架會直接返回狀態碼為 422 的 HTTP 回應。
換言之,如果你將post_id
標記為str
,則 Django Ninja 會自動將post_id
轉換為字串。
還記得剛開始接觸 Django Ninja時,我非常驚嘆竟然可以充分運用 Python type hints 到這般程度,讓它不僅僅是為了型別安全而服務,而是融入到整個 API 開發流程中。
View 函式中的 request 參數
上面的例子中,有個值得注意的細節,就是 view 函式的第一參數——request
。
在 Django 中,view 函式的第一個參數必定為 request。這個參數名稱可以自行定義,但通常會命名為request
。
收到 HTTP 請求時,Django 會將整個請求打包成一個HttpRequest
物件,並將它作為第一個參數傳給 view 函式,所以它必不可少。
request
參數在 Django 和 Django REST framework 中非常重要,因為它常用來取得請求的查詢參數、body 等內容。
在 Django Ninja 中,這些資料會直接透過函式參數來取得,因此request
雖然仍不可少,但使用頻率較低。
下一步
接下來,我們將深入探討 Django Ninja 處理請求的具體細節。
下一篇將聚焦於路徑參數(path parameters),並探討如何與 Django 原生的 path converters 搭配使用。敬請期待!