# 目錄結構
由於大多數網路上及教學,專案大都只含一個 app,而實際上多數商用專案及實際情況都會需多管理多個 apps,這邊就來看看多個 app 的整個專案結構會變如何
先看一開始還沒有拆分多個 Apps 前的 Django 專案結構:
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 後的專案結構:
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.py、blog_views.py 來區分不同的 API 視圖,
- 但考慮到專案未來擴展性,
models.py可能會變得非常雜亂及龐大,且不同的資料表欄位可能會衝突,Ex: product 與 blog 都會有 Tag 資料表,這樣會造成混淆及不易管理 - 因此決定將不同的功能拆分成不同的 apps,並各自管理自己的
models.py、views.py、urls.py等
# 專案目錄結構差別圖

# 程式修改
# apps
由於大幅移動的目錄結構,所以再次執行 python manage.py runserver 時會出現找不到模組的錯誤 ModuleNotFoundError: No module named 'api.apps' 是正常的,這時候就需要進行一些程式碼的調整
首先 apps 的部分就跟先前稍微不同的,大多都是路徑的調整而已,像是 apps.py 就需要調整成 api.products,這樣 Django 才能正確的辨識到這個 app
產品的:
# 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'
文章的
# 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
# backend/settings.py
INSTALLED_APPS = [
...
# 註冊 api(後端資料夾名稱) app
'api.products.apps.ProductsConfig',
'api.blog.apps.BlogConfig',
# DRF
'rest_framework',
# cors
'corsheaders',
]
# urls
然後在專案的路由總管 urls.py 中也要調整路由的設定成我們更新完的路徑
# api/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('api/products/', include('api.products.urls')), # 產品 API
path('api/blog/', include('api.blog.urls')), # 部落格 API
]
# 測試兩個 apps 是否都能正常運行
解決所有路徑問題後,就可以來測試兩個 apps 是否都能正常運行
# 文章管理後端
# views
先簡單的在 blog 中新增一個 API 視圖,並回傳一個 JSON
# 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
from django.urls import path
from .views import BlogPostListView
urlpatterns = [
path('', BlogPostListView.as_view(), name='blog-list'),
]
# 成功畫面

# 產品管理後端
在產品的部分主要會有的問題就是由於先前已經 migrate 過資料表,而 Django 會使用 app_label_modelname 的格式來命名資料表,所以會有 django.db.utils.OperationalError: (1050, "Table 'products_product' already exists") 找不到指定資料表的錯誤
所以先去 MySQL 中刪舊的 api_product..api_productimage... 資料表
DROP TABLE api_product,...;
再進行一次 migrate 並新增資料就能正常啟動服務了
# 成功畫面

