資料查詢與過濾(下)FilterSchema 多欄位查詢

2024 iThome 鐵人賽

這是 Django Ninja 系列教學的第 27 篇。

上篇中,我們學習了 Django ORM 的Q物件和 Django Ninja 的 FilterSchema,但後者感覺只學了一半。

討論比較多的是,view 函式中使用 FilterSchema 的參數定義方式——這確實很重要,但這只是 FilterSchema 的一部分。

本篇要來補完剩下的內容:

  1. 完善 FilterSchema:使用「更道地」的寫法,釋放 FilterSchema 真正的力量
  2. 實作更進階的欄位查詢功能:多欄位查詢——篩選日期區間。
  3. 追加實作第 20 篇學到的「跨欄位驗證」:驗證查詢參數的日期區間是否合法

看來又是資訊滿滿的一篇,話不多說,直接開始吧!

本文所有的程式碼變動,可參考這個 PR

資料查詢與過濾(上)FilterSchema 介紹

2024 iThome 鐵人賽

這是 Django Ninja 系列教學的第 26 篇。

查詢」是 API 中常見的附加需求,本質上是對資料的過濾(filtering)與篩選

無論是篩選文章、商品,還是查詢用戶,根據不同條件來過濾資料並獲得結果,可說是大部分專案的必備功能。

在 view 函式中,實作查詢最簡單的方式,就是使用 Django ORM 的過濾方法。例如,我們可以用filter方法來根據特定條件篩選 QuerySet。

這種方法簡單直接,適合基本的查詢需求。然而,它也有其局限性——隨著欄位與需求的增加,查詢條件可能變得越來越複雜,導致程式碼冗長且難以維護。

為了解決這一問題,Django Ninja 提供了 FilterSchema,讓我們可以用更「結構化」的方式,定義並管理查詢條件。

本文將介紹 FilterSchema,一步步實作與講解,讓你了解如何在 Django Ninja 中使用 FilterSchema,實現更加靈活、模組化的 API 查詢功能。

本文所有的程式碼改動,可參考這個 PR

分頁(下)自定義分頁類別

2024 iThome 鐵人賽

這是 Django Ninja 系列教學的第 25 篇。

上一篇我們介紹了 Django Ninja 的內建分頁器,並用它實作了簡單的分頁功能。

雖然內建的PageNumberPagination確實方便,但在很多時候,我們仍需要一些客製化功能。

為了實現這個目的,你需要自定義一個分頁類別

不過別擔心,這種自定義,並非從零開始。而是繼承 Django Ninja 所提供的基礎分頁類別,再進行自己的「加工」。

這篇文章就要來教你怎麼做。

本文所有的程式碼變動,可參考這個 PR


客製化需求

除了基本的分頁,我們還希望能夠:

  • 允許客戶端選擇每頁顯示的資料數量,可選範圍限定在 1 至 100 之間。
  • 在回應中新增兩個欄位,顯示當前的分頁資訊
    • 當前頁數(page)。
    • 每頁顯示數量(per_page)。

這無疑是很常見的需求。我們將透過自定義分頁類別,來實現這些功能。

話不多說,直接開始!

分頁(上)Django Ninja 的內建分頁器

2024 iThome 鐵人賽

這是 Django Ninja 系列教學的第 24 篇。

分頁(pagination)功能,就算在資料量較少的小型專案,也具有相當的重要性。

沒分頁,API 照樣能運作——只是效能會受到影響,特別是在資料量大的情況下。

當 API 一次回傳大量資料時,不僅會增加伺服器負擔,還可能導致客戶端處理緩慢,甚至出現超時記憶體不足等問題。

透過分頁,我們可以避免一次性傳輸大量資料,提高 API 的效能,同時提升使用者的體驗。

這個主題將分為上、下兩篇,介紹如何在 Django Ninja 中實作分頁功能——從內建的分頁器自定義分頁類別,以滿足不同需求。

本文所有的程式碼變動,可參考這個 PR


分頁的重要性

分頁的核心作用將大量資料拆分成小部分傳輸,每次只給一些,從而避免效能問題。

具體而言,分頁能夠幫助我們:

  1. 減少伺服器壓力:不必一次回傳全部資料,只需處理單個頁面的資料。
  2. 提升網路傳輸速度:傳輸太大量的資料會增加網路延遲和資料丟失的風險,通過分頁,能有效降低傳輸需求
  3. 提升使用者體驗:客戶端可以快速獲取並顯示初步資料,無需等待所有資料傳輸完成。同時,分頁還能減少客戶端處理大量資料的壓力

因此,無論專案規模大小,實作高效的分頁策略,對 API 的擴充性與使用者體驗,都有明顯幫助

了解了分頁的重要性後,我們來開始實作吧!

檔案上傳——Django UploadedFile 介紹

2024 iThome 鐵人賽

這是 Django Ninja 系列教學的第 23 篇。要開始介紹進階功能了!

現代 Web 服務中,檔案上傳是一個常見的情境。

無論是使用者上傳照片、夾帶附件,檔案上傳都是不可或缺的功能。

本文介紹如何在 Django Ninja 中實現圖片上傳功能,以使用者「上傳大頭貼」(以下都稱為 avatar,因為大頭貼感覺太可愛🥹)API 為例,帶你一步步了解這個過程。

本文所有的程式碼改動,可參考這個 PR


不過,在此之前,我們要先了解,本章有哪些主題。

第六章「API 進階功能」簡介

對 API 專案而言,進階功能能幫助我們應對複雜場景大型專案的挑戰。

雖然這是一個入門指南,但我們仍會涵蓋一些常見的進階功能,這些功能不僅提升 API 的靈活性,還能增強了系統效能與使用者體驗。

本章共有 5 篇,介紹 3 個常見的進階功能:

這些技術不僅對大型專案至關重要,也讓你能在 API 開發中,有效應對多變的需求。

錯誤處理(下)全域錯誤處理——使用 Exception Handlers

2024 iThome 鐵人賽

這是 Django Ninja 系列教學的第 22 篇。

上一篇文章,我們學習了如何操作HttpError,並建議你只在 view 函式中使用它。

但光是這樣,專案 API 的錯誤處理,還遠遠不夠完善,至少有 3 個常見問題待解:

  1. Schema 中的驗證方法 ,如果不要raise HttpError,那要怎麼做才好?
  2. 我們應該如何處理其他類型的錯誤,例如資料庫操作錯誤?
  3. 如何確保不同 API 錯誤的回應格式一致

這些問題都指向了一個更大的需求:我們需要一個全面的錯誤處理機制

這篇文章,就要來回答這些問題。所有的程式碼改動,可參考這個 PR

錯誤處理(上)HttpError 與自定義 HTTP 回應

2024 iThome 鐵人賽

這是 Django Ninja 系列教學的第 21 篇。

在軟體開發中,錯誤處理是一個不容忽視——但常常被忽視——的環節。

不誇張地說,錯誤處理是一個「做得好沒人誇,做不好系統就慘兮兮」的議題。

沒關係,我們還是盡可能把自己做好

Django Ninja 使用 Pydantic 進行資料驗證,失敗時,預設回應「422 Unprocessable Entity」。

然而,我們有時候需要回應「400 Bad Request」或別的狀態碼,以符合現實業務需求團隊開發習慣

總之,無論出於何種原因,我們想自訂錯誤訊息、格式,以及回應的狀態碼,而不使用 Django Ninja 預設的 422 回應——不得不說,這個制式回應的資訊有點多、結構有點複雜,因為它要兼容各種情況。

本文將介紹如何自定義錯誤處理與回應——使用 Django Ninja 內建的HttpError

所有的程式碼改動,可參考這個 PR


Django Ninja 的自動錯誤處理

上一篇我們提到,如果你在 Schema 的驗證方法中,拋出ValueError錯誤,Django Ninja 將會自動捕捉並回應

事實上,不止ValueError,Django Ninja 還會替你處理以下這幾種錯誤:

  • pydantic.ValidationError,來自 Pydantic 的驗證錯誤,這是為何當 Schema 欄位有問題時,我們會直接收到 422 回應。
  • 此外,Django Ninja 還內建了一個 ninja.errors.ValidationError,這些錯誤同樣會返回 422。
  • ninja.errors.HttpError:這是本文的重點,下面會介紹。

這些都是 Django Ninja 會自動捕捉的錯誤,但不是每一種都給出制式的 422 回應——第三種就不是。