回應(二)用 Schema 建立巢狀結構回應

2024 iThome 鐵人賽

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

在 API 開發中,我們經常會遇到關聯模型之間的資料需要同時返回的情況。

特別是在處理「一對一」或「一對多」關聯時,多層結構往往是常態。

我們希望以巢狀結構Nested Objects)的方式返回資料,這樣可以讓 API 的使用者一次取得必要資訊,而不需要進行多次請求。

本文將繼續使用並擴充「單一文章資訊」API 這個範例,講述如何在 Django Ninja 中實現巢狀結構回應,讓我們的 API 回應更加豐富、有體系。

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


一、問題背景

在之前的 API 設計中,「取得單一文章資訊」的回應包括了文章資訊及作者的 id

1
2
3
4
5
6
7
class PostResponse(Schema):
id: int
title: str
content: str
author_id: int
created_at: datetime
updated_at: datetime

有經驗的開發者都知道,無論是id還是author_id,通常不是給服務的使用者看的——而是給前端人員靈活運用的。

比如在系統的畫面中,文章可能包括作者的個人資訊連結,點進去可以看到作者資訊。此時前端必須透過 id,再呼叫另一支 API「取得用戶資訊」來獲得額外的內容。

如果額外資訊很多,這樣的「解耦」設計是非常合理的。但如果我們希望一併呈現作者的「必要資訊」,那分次呼叫的設計就略嫌拖沓

所以我們需要巢狀結構

API 可以直接在回應中,嵌入作者的「必要資訊」,這樣用戶就不必再進行多次請求。這裡我們以一併顯示作者的「名字」和「email」為例。

回應(一)Django Ninja 處理 HTTP 回應

2024 iThome 鐵人賽

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

這一篇要正式進入「HTTP 回應」環節,也就是第三小節。

本節將透過 4 篇文章,介紹 Django Ninja 如何處理 HTTP 回應

我們會講述更多 Schema 用法,透過這些技巧,你能夠精確地控制 API 的輸出格式。無論是單一物件回應,還是複雜的嵌套結構,接下來都會一一提及。

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

請求(四)Request Body 與 Schema 介紹

2024 iThome 鐵人賽

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

經過前幾篇的介紹,我們已經學習了如何處理路徑與查詢參數。但在現實世界中,我們往往還需要處理更複雜的請求資料

比如用戶提交的表單、上傳的檔案等等。對於 API 而言,最常見的就是 JSON 格式的 request body

這一篇將探討 Django Ninja 如何處理 request body,並介紹如何透過 Schema 來定義與驗證資料。

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


一、什麼是 Request Body?

Request body 指的是隨著 HTTP 請求一同傳送的資料,通常用於POSTPUT需要建立或更新「資源」的請求。

這些資料不會出現在 URL 中,而是以 JSON 或其他格式(如 XML、form-data)作為請求的主體。

例如,當用戶要發表一篇新文章時,可能會傳送以下 JSON 格式的 request body:

1
2
3
4
{
"title": "我的第一篇文章",
"content": "這是我在忍者論壇的第一篇文章,希望大家喜歡!"
}

這個 request body 包含了titlecontent兩個欄位,Django Ninja 將協助我們處理這些資料並進行驗證。

請求(三)查詢參數 - Query Parameters

2024 iThome 鐵人賽

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

上一篇我們討論了,請求 URL 中關於路徑參數的處理方式。

本文將介紹查詢參數(query parameters),這是 RESTful API 中用來傳遞過濾條件額外資訊的重要部分。

處理查詢參數在 Django Ninja 中非常簡單直觀,我們可以透過多種方式來達成。

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


一、什麼是查詢參數?

查詢參數是 URL 中的可選參數,通常位於 path 的後方,以?key=value的形式出現,用來傳遞額外的資訊

例如,當我們需要過濾某位作者的文章時,URL 的 path 可能會這樣寫:

1
/posts/?author=john

URL 傳遞了一個查詢參數author=john,表示我們希望過濾出由 John 撰寫的文章。

請求(二)路徑參數 - Path Parameters

2024 iThome 鐵人賽

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

上一篇文章中,我們介紹了 Django Ninja 如何處理 HTTP 請求,並強調了它與 Python type hints 之間的緊密結合。

本篇將探討 Django Ninja 中,路徑參數(path parameters的應用與細節,這在處理 HTTP 請求時極為常見,尤其是在 RESTful API 中。

本文對範例專案的程式碼改動,都集中在這個 PR


一、什麼是 Path Parameters?

Path parameters 是構成 URL 的一部分,它們位於網址路徑(path)中的特定位置,根據不同的值(參數)來決定傳入的內容,用來動態指定資源

我們不妨先了解一下,path 在整個 URL 中的位置:(圖片取自維基百科

點圖可放大

從圖中可以看出,路徑(path)是 URL 的一部分——而且是必要部分

不過請注意,path parameters 只是 Django、Django Ninja 這類框架所提供的一種「功能」。對 URL 本身而言,path 就是 path,也就是單純的字串而已。

路徑參數例子

舉一個簡單的例子,讓我們可以更好地理解 path parameters 的概念。

1
@router.get(path='/posts/{post_id}/')  # {post_id} 就是路徑參數

實際請求時,123就是透過路徑參數,代表特定文章的 id:

1
GET /posts/123

可想而知,如果是456789,你會得到不同的結果。

這使得 API 具有彈性,可以針對不同的資源進行操作,而不必為每一個資源建立不同的路由——它們的端點與路由都是相同的,只是「參數」不同。

請求(一)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 函式的這些關鍵部分,包括但不限於:

  1. 處理 HTTP 請求的參數與 body。
  2. 處理 HTTP 回應內容的序列化與格式化。
  3. 資料驗證與錯誤處理。

它們共同構成了 Django Ninja 的主要功能。

本節和下一節,將集中討論上述 3 點中的前兩點——請求與回應。至於第三點,將留到第五章再行介紹。

路由(下)Django Ninja 路由設定

2024 iThome 鐵人賽

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

上一篇文章中,我們介紹了 Django 傳統的路由設定方式。

如前所述,雖然有一個「路由清單」確實不錯。但隨著專案規模的擴大,不斷來回切換urls.pyviews.py將大幅增加開發者的認知負擔——拉長了開發時間,還更容易導致錯誤。

Django Ninja 採用了一種更現代化的路由設計,結合了 Flask 和 FastAPI 的設計理念。不僅簡化了路由的定義,還提升了程式碼的可讀性,讓路由與 view 函式緊密結合

範例專案動態

本文關於路由設定的程式碼改動,可以參考這個 PRPull Request)。

範例專案合併了本文的 PR 後,已經正式成為一個「API 專案」,不過它目前(指這個 commit 狀態)尚無法正常運作,因為我們還沒有完善 view 函式的基本功能。

你可以一步步地跟著每一篇的 PR,來學習當次的新內容。這也是我為文章建立 PR 的用意所在。