Let's Django!Let's Django!

這是 Django Tutorial 的第 6 篇、DRF 系列的第 2 篇。

範例程式碼可參考我的 GitHub 專案

本文相關的程式碼改動,都集中在這個 PR


上一篇我們介紹了 Django 和 Django REST framework(以下簡稱 DRF)之間的區別,與它們各司其職的角色定位。

兩者相輔相成,讓 Django 在這個「前後端分離」的時代,還能佔有一席之地。

接下來,我們要開始動手實作 API。

系列:Django REST framework 教學

本文主旨

本文的目標:建立一個 Django API,並確保它正常運行。

為了達到這個目標,我們需要完成以下三件事:

  1. 安裝 Django REST framework 套件。
  2. 設定 Django 的settings.py,加入 DRF 相關內容。
  3. 實作第一個路由(router)與 API。

就這麼簡單,讓我們直接開始吧!


安裝 Django REST framework 套件

安裝之前,請務必先啟動專案的虛擬環境,以下命令都是在虛擬環境中執行。

首先,我們需要安裝 Django 和 Django REST framework。可以使用以下指令:

1
2
pip install django
pip install djangorestframework

接著,建立一個新的 Django 專案和應用程式(Django app):

1
2
3
django-admin startproject myproject
cd myproject
django-admin startapp myapp

以上是一般範例。

如果以 Django-Tutorial 為例(使用 Poetry),則指令如下:

1
2
poetry add django@^4.2
poetry add djangorestframework

建立 Django 專案與 app:

1
2
3
django-admin startproject DjangoTutorial
cd DjangoTutorial
django-admin startapp post

以下解說都直接採用我的範例專案


我的 Django project 命名習慣

一個尋常的 Django 專案,通常是這樣的結構:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
├── django_project
├── django_project
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── app1
│ ├── __init__.py
│ ├── admin.py
│ ├── models.py
│ ├── urls.py
│ └── views.py
├── app2
├── app3

最上層我稱為 repo 專案,也就是專案的根目錄

第二層的 django_project 即本段標題中所謂 Django project,裡面有settings.py等「面向整個專案」的設定。

你可能注意到,我的 Django project 用的是大駱峰式命名(DjangoTutorial),而不是典型的小寫加底線(django_tutorial)。

理由很簡單——為了快速區別 Django project 和其它的 Django app 目錄。

區別 Django project 和 Django app

畢竟它們都一起放在整個 repo 專案底下(這是 Django 預設的專案組織方式),隨著 Django app 愈來愈多,透過命名風格來區分二者,可能是最簡單且省力的方式。

雖然這和 PEP 8 的原則(即模組名稱應該使用「小寫 + 底線」命名)有點出入,但我還是推薦你這麼做。

至於 repo 專案的命名,則沒有限制,可依個人需求而定。我選擇 Django-Tutorial 是為了看起來顯眼且好辨識。

但如果是「認真的」開源專案,建議還是採用「aa-bb-cc」格式。


講完命名,我們進入設定環節。

設定settings.py

打開 DjangoTutorial/settings.py,為 INSTALLED_APPS 新增以下內容:

1
2
3
4
5
6
7
8
9
10
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework', # 新增
'post', # 新增
]

新增部分是最後 2 行,其餘則是預設值

每一個我們建立的 Django app 都要加到這個INSTALLED_APPS,而 DRF 本身也要。


Django 路由設定

端點endpoint)代表特定的 URL,是 API 的「入口」。

路徑(path)是 URL 的一部分——而且是必要部分。圖解如下:

en.wikipedia.org/wiki/URL,點圖可放大en.wikipedia.org/wiki/URL,點圖可放大

路由(router)則是連結端點與實際負責處理請求的 view 函式之間的橋樑,也就是「如何分配請求給處理者」的機制,或者說規則

我們再複習一下 Django 的路由基本做法:

  1. 建立 Django app 的二級路由。
  2. 設定 Django project 的一級路由。

我也看過把所有路由統一放到 Django project 的urls.py做法,但這屬少數。

App 二級路由

首先,在 Django app 底下新增urls.py。這個檔案預設上沒有,我們要自行建立。

post/urls.py內容:

1
2
3
4
5
6
from django.urls import path
from post.views import hello_world # 這個 view 函式目前還沒寫

urlpatterns = [
path('hello/', hello_world),
]

path是 Django 內建的路由函式,沒有它,你的請求就到不了負責處理請求的 view 函式。

path函式的第一個參數,是具體的 path 字串。如上圖,path 是端點的一部分,即上面程式碼中的'hello/'

每一個 app 級路由,都要指向特定的 view 函式,也就是path函式的第二個參數——hello_world,儘管我們實際上還沒有撰寫它的內容。

專案一級路由與前綴

DjangoTutorial/urls.py中的一級路由:

1
2
3
4
5
6
7
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path('admin/', admin.site.urls),
path('post/', include('post.urls')),
]

'post.urls'就是 post app 的urls.py

通常我們會對它加上一個 path 前綴,比如'post/'

有了'post/'這個前綴,在 post app 的所有路由設定中,都不必再一一加上,這做法有助於路由的管理與維護。

經過這些設定,我們第一個路由就完成了。

但是,我們還沒有寫 API 的內部邏輯呢!


完成第一個 API

有了端點和路由,剩下的就是 view 函式。

post/views.py中建立一個新的 view 函式:

1
2
3
4
from django.http import JsonResponse

def hello_world(request):
return JsonResponse({"message": "Hello, world!"})

這還不是一個 DRF 的 view 函式,但它可以正常運作。

它將回應一個內容為 JSON 的 HTTP response——這是典型的 API 行為。

此時,我們在 path「/post/hello/」已經定義了一個 API。

啟動伺服器,測試 API

大功告成,我們立刻來測試它!

直接啟動 Django 內建的開發伺服器

1
2
3
4
5
❯ python manage.py runserver
...
Django version 4.2.13, using settings 'DjangoTutorial.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

伺服器在本機啟動後,我們預期這個端點,會回應我們剛定義的 JSON response:

果然如此!可見我們的 API 已正常運作。


小結:路由很重要

Django 路由設定不難,甚至有些死板。但它們是連接請求與處理邏輯的關鍵部分。

正確的路由確保 API 的正確運行。透過清晰、簡潔的路由設計,可以更容易地管理和擴展我們的 API 服務。

DRF 的路由規則幾乎完全遵循了 Django 原有的做法,所以沒有特別介紹。

本篇對於熟悉 Django 的人可能沒有太多新東西——這是好事。

下一篇,我們將進入重頭戲——view 函式。