2024 iThome 鐵人賽2024 iThome 鐵人賽

這是 Django Ninja 系列教學的第 7 篇。我們來到系列的第三章

第三章是全系列的重頭戲,因為我們要介紹 Django Ninja 的核心部分——API

我把本章分成了三個小節:

  1. 第一節:路由(Router)
  2. 第二節:請求(Request)
  3. 第三節:回應(Response)

第三章也是唯一有區分小節的篇章。

現在我們進入第一節——路由。讓我們先了解一下本節的學習重點。

快速導覽

👉 完整系列目錄點此查看
👉 程式碼範例GitHub 範例專案


本節重點

本節一共有兩篇,分別是:

  • 卷 7:路由(上)傳統 Django 路由做法
  • 卷 8:路由(下)Django Ninja 路由設定

為什麼要這樣安排呢?因為端點與路由是 API 請求的起點

沒有它們,你的 view 函式根本無法接收請求,更不用說回應了。因此,路由設定必須放在第一位,作為 API 開發的學習入口。

所謂的「端點」(endpoints),你就簡單想成 API 所在的 URL 就可以了。

本文主旨

其次,Django Ninja 的路由設定與傳統 Django 或 Django REST framework(以下簡稱 DRF)的路由設定有很大的不同,反而更接近 FastAPI 或 Flask 風格。

這是我在學習 Django Ninja 時遇到的第一個門檻(畢竟我寫了 2 年的 DRF😅),所以決定分成上下兩篇文章詳細解說,幫助你打好基礎、減少混淆。

本文的重點是介紹 Django 傳統路由的設定方式。讓我們開始吧!


什麼是路由(Routers)

路由(Router)是 Web 服務的重要元件之一,它負責將客戶端(通常是瀏覽器)發送的 HTTP 請求,對應到正確的處理邏輯

在 Django 中,路由就是決定「哪個請求應該由哪個 View 來處理」的機制。

當客戶端訪問特定的 URL(我們稱為「端點」)時,Django 伺服器會根據這個 URL,找到對應的處理函式來執行特定邏輯。

這個「對應(mapping)」的過程,就是路由的核心職責。


Django 路由介紹

Django 的路由機制主要透過 urls.py 中的設定,來管理不同層級的路由結構,並通過一級路由和二級路由,加以整合、組織所有端點。

至此,我們已經提到了 Django 路由的三個關鍵元素

  • 一級路由
  • 二級路由
  • urls.py

以下是對它們的介紹。

一級路由

一級路由是「專案級別」的路由,通常位於 Django 專案目錄底下(即範例專案中的 NinjaForum 目錄)的 urls.py 中。

一級路由主要用來為每一個 Django app 分別加上全 app 統一的「路由前綴」,並整合來自所有 app 的路由

以本專案為例,它可能會長這樣:

1
2
3
4
5
6
7
8
9
# NinjaForum/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path('admin/', admin.site.urls),
path('posts/', include('post.urls')), # 處理 post app 的路由
path('users/', include('user.urls')), # 處理 user app 的路由
]

這裡的 urlpatterns 是 Django 的一級路由。它將 /posts//users/ 路徑分別指向 post 和 user app 的二級路由,作為各 app 二級路由的統一前綴。

二級路由

二級路由是各 Django app 自行管理的路由。直接對應 app 本身的 view 函式:

1
2
3
4
5
6
7
8
# post/urls.py
from django.urls import path
from post import views

urlpatterns = [
path('', views.get_posts)
path('<int:post_id>/', views.post_detail),
]

將一級與二級路由的邏輯重新組合後,上述兩個 app 級路由,實際的端點是:

  1. /posts/ :取得所有文章。
  2. /posts/<int:post_id>/:取得特定文章細節。

這種層級式的路由結構不僅使 URL 更有組織,也讓不同 app 的功能更加模組化

舉例而言,如果我們想要為 user app 新增一個「獲取用戶資料」API,我們只需要在 user app 的 urls.py 中建立相對應的路由即可,不需修改專案級別的路由設定。


專案架構圖

鳥瞰的角度可能會更清楚。

就 Django 傳統路由部分,整個範例專案的目錄與檔案結構如下(已省略無關部分):

1
2
3
4
5
6
7
8
9
10
├── NinjaForum
│ ├── urls.py # 專案一級路由
│ ├── ...
├── post
│ ├── urls.py # app 二級路由
│ ├── ...
├── user
│ ├── urls.py # app 二級路由
│ ├── ...
├── ...

這樣的結構在 Django 專案中十分常見,同時也是 DRF 的標準做法。

專案一級路由負責全域的入口,二級路由負責 app 中 view 函式的配對。這樣的設計,使得專案架構更具模組化與擴展性。


Django 傳統路由的優點與缺點

Django 傳統的路由機制藉由專案與 app 層級的 urls.py,來組織並定義完整的 URL 路徑(端點),這樣的設計有好有壞,讓我們來探討其中的利弊

優點:清晰的端點清單

Django 傳統路由的一大優點就是所有的端點、路由都集中在 urls.py。這意味著開發者可以一眼看出目前所有的 API 端點(app 部分),例如:

1
2
3
4
5
6
7
8
9
# app 層級 urls.py
from django.urls import path
from . import views

urlpatterns = [
path('home/', views.home, name='home'),
path('about/', views.about, name='about'),
path('contact/', views.contact, name='contact'),
]

urls.py 就像路由目錄一樣,一目了然。

缺點:對照端點與 view 函式需要來回跳轉

如前所述,路由負責連接端點與 view 函式。

由於每個端點都需要對應一個 view 函式,而對應的 view 函式通常放在 views.py

對應示意圖(僅供參考)對應示意圖(僅供參考)

這帶來了一個問題:開發者需要在 urls.pyviews.py 之間來回切換才能完整理解一個端點與背後的實現邏輯。

這樣的「不直觀」不僅增加了開發時的認知負擔,也容易在修改 API 時發生錯誤。

此外,隨著專案規模不斷擴大,urls.py 中的端點清單會越來越長——要找到對應的 view 函式變得耗時且繁瑣,進一步增加了出錯的可能。


小結

本文中,我們深入了解了傳統 Django 的路由設計,並探討了其優缺點。

這種結構化的設計讓路由的管理更加模組化,但也引發了在大型專案中維護和閱讀困難的問題。

接下來,我們將探索 Django Ninja 如何提供更簡潔的路由機制,並與傳統 Django 路由進行比較。

The Django Ninja Way

Django Ninja 採用了一種更現代化的方式,來處理路由和 view 函式——它將兩者緊密結合,提供了一種更直觀的手段來定義 API 端點。(其實大家都是學 Flask 的☺️)

不僅大幅減少了在不同檔案間切換的需求,還提高了程式碼的可讀性和維護性。

下一篇,就讓我們來了解 Django Ninja 的路由機制,看看它是如何改善這些問題的。