2024 iThome 鐵人賽2024 iThome 鐵人賽

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

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

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

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

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

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


本節導覽

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

  • 卷 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 的路由機制,看看它是如何改善這些問題的。