2025 OEM 網站開發筆記 [101] - 從單一到多個 apps 的 Django 管理指南:專案結構調整、模組化後端設計與維護策略

Posted by Young on 2025-03-05
Estimated Reading Time 4 Minutes
Words 1.1k In Total

目錄結構

由於大多數網路上及教學,專案大都只含一個 app,而實際上多數商用專案及實際情況都會需多管理多個 apps,這邊就來看看多個 app 的整個專案結構會變如何

先看一開始還沒有拆分多個 Apps 前的 Django 專案結構:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
my_project/

├── manage.py # Django CLI 入口
├── requirements.txt # Python 依賴套件

├── backend/ # Django 專案設定
│ ├── __init__.py
│ ├── asgi.py # ASGI 入口 (WebSocket)
│ ├── settings.py # Django 設定檔
│ ├── urls.py # 全域路由
│ ├── wsgi.py # WSGI 入口 (部署)

├── api/ # 單一 API App (未拆分多個 apps)
│ ├── __init__.py
│ ├── admin.py # Django Admin 註冊
│ ├── apps.py # Django App 設定
│ ├── base_views.py # 共用的視圖函數
│ ├── models.py # 所有資料表定義
│ ├── serializer.py # Django REST Framework (DRF) 序列化
│ ├── tests.py # 測試檔案
│ ├── migrations/ # 資料庫遷移檔案
│ ├── urls/
│ ├── product_urls.py # 路由目錄 (可能用來拆分 API 路由)
│ ├── views/
│ ├── product_views.py # API 視圖目錄

多新增 blog 這個 apps 後的專案結構:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
my_project/

├── manage.py
├── README.md
├── requirements.txt
├── .gitignore
├── .env
├── backend/ # Main project folder
│ ├── __init__.py
│ ├── settings.py # Or a settings/ folder with separate files (base.py, dev.py, prod.py)
│ ├── urls.py
│ ├── wsgi.py
│ ├── asgi.py│
├── api/ # (apps) Directory for all Django apps
│ ├── __init__.py # Makes 'apps' a Python package
│ ├── products/ # (app1) 產品管理 App
│ │ ├── migrations/
│ │ ├── __init__.py
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── models.py
│ │ ├── tests.py
│ │ ├── views.py
│ │ ├── urls.py # App-specific URL configuration
│ └── blog/ # (app2) 文章管理 App
│ ├── migrations/
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ ├── views.py
│ ├── urls.py
└── static/ # Global static files (e.g., CSS, JavaScript, images)
├── css/
├── js/
└── images/

原本只打算單純的透過在 urls 以及 views 目錄下命名不同的 Ex: product_views.pyblog_views.py 來區分不同的 API 視圖,

  • 但考慮到專案未來擴展性, models.py 可能會變得非常雜亂及龐大,且不同的資料表欄位可能會衝突,Ex: product 與 blog 都會有 Tag 資料表,這樣會造成混淆及不易管理
  • 因此決定將不同的功能拆分成不同的 apps,並各自管理自己的 models.pyviews.pyurls.py

專案目錄結構差別圖

dir_before_after

程式修改

apps

由於大幅移動的目錄結構,所以再次執行 python manage.py runserver 時會出現找不到模組的錯誤 ModuleNotFoundError: No module named 'api.apps' 是正常的,這時候就需要進行一些程式碼的調整

首先 apps 的部分就跟先前稍微不同的,大多都是路徑的調整而已,像是 apps.py 就需要調整成 api.products,這樣 Django 才能正確的辨識到這個 app

產品的:

1
2
3
4
5
6
7
8
9
# api/products/apps.py

# class ApiConfig(AppConfig):
# default_auto_field = 'django.db.models.BigAutoField'
# name = 'api'

class ApiConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'api.products'

文章的

1
2
3
4
5
6
# api/blog/apps.py

class BlogConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'api.blog'
verbose_name = "文章管理" # 🔹 Django Admin 會顯示「文章管理」

settings

然後在 INSTALLED_APPS 中也多註冊新增的 app

1
2
3
4
5
6
7
8
9
10
11
# backend/settings.py
INSTALLED_APPS = [
...
# 註冊 api(後端資料夾名稱) app
'api.products.apps.ProductsConfig',
'api.blog.apps.BlogConfig',
# DRF
'rest_framework',
# cors
'corsheaders',
]

urls

然後在專案的路由總管 urls.py 中也要調整路由的設定成我們更新完的路徑

1
2
3
4
5
6
7
8
9
# api/urls.py

urlpatterns = [
path('admin/', admin.site.urls),
# path('api/products/', include('api.urls.product_urls')),

path('api/products/', include('api.products.urls')), # 產品 API
path('api/blog/', include('api.blog.urls')), # 部落格 API
]

測試兩個 apps 是否都能正常運行

解決所有路徑問題後,就可以來測試兩個 apps 是否都能正常運行

文章管理後端

views

先簡單的在 blog 中新增一個 API 視圖,並回傳一個 JSON

1
2
3
4
5
6
7
8
9
10
11
12
# api/blog/views.py

from django.http import JsonResponse
from django.views import View

class BlogPostListView(View):
def get(self, request):
data = {
"message": "HEEEEEEEEEEEELLLLOOOOOOOOOOOOOO~~~~~ (BlogPostListView)",
"posts": []
}
return JsonResponse(data)

urls

1
2
3
4
5
6
from django.urls import path
from .views import BlogPostListView

urlpatterns = [
path('', BlogPostListView.as_view(), name='blog-list'),
]

成功畫面

blog_response

產品管理後端

在產品的部分主要會有的問題就是由於先前已經 migrate 過資料表,而 Django 會使用 app_label_modelname 的格式來命名資料表,所以會有 django.db.utils.OperationalError: (1050, "Table 'products_product' already exists") 找不到指定資料表的錯誤

所以先去 MySQL 中刪舊的 api_product..api_productimage… 資料表

1
DROP TABLE api_product,...;

再進行一次 migrate 並新增資料就能正常啟動服務了

成功畫面

product_response


若您覺得這篇文章對您有幫助,歡迎分享出去讓更多人看到⊂◉‿◉つ~


留言版