深入理解 Django 的 BASE_DIR
更新日期: 2025 年 2 月 24 日
本文為 資料庫正規化 基本介紹系列文,第 6 篇:
在 Django 專案中,BASE_DIR
是一個關鍵的變數,通常定義在 settings.py
檔案中。
它的作用是確定專案的 根目錄(Root Directory),幫助我們在專案內部建立相對路徑,而不需要硬編碼絕對路徑。
這樣的設計讓 Django 專案在不同的環境(開發、測試、部署)中更靈活。
在這篇文章中,我們將深入探討 BASE_DIR
的原理,解析它的定義方式,並了解它在 Django 中的應用!🚀
os.path
是什麼
Python 的 os.path
是處理 檔案與目錄路徑 的標準模組,它提供了許多實用的方法來操作路徑。我們來看看 BASE_DIR
所用到的幾個關鍵函式,以及其他常見的 os.path
方法。
os.path.abspath(path)
– 取得絕對路徑
這個函式可以將相對路徑轉換為 絕對路徑:
import os
print(os.path.abspath("settings.py"))
# 假設當前目錄為 /home/user/myproject/
# 輸出: /home/user/myproject/settings.py
這確保我們獲得的路徑不會因為當前工作目錄不同而產生錯誤。
os.path.dirname(path)
– 取得上層目錄
這是 BASE_DIR
的核心函式,它可以獲取 某個檔案的上一層目錄:
path = "/home/user/myproject/myproject/settings.py"
print(os.path.dirname(path))
# 輸出: /home/user/myproject/myproject
如果我們再執行一次 os.path.dirname()
,就能夠獲得 專案的根目錄:
print(os.path.dirname(os.path.dirname(path)))
# 輸出: /home/user/myproject
BASE_DIR
是什麼?
在 Django 專案的 settings.py
中,你通常會看到這樣一行程式碼:
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
這段程式碼的目的是 動態獲取專案的根目錄路徑,以確保程式可以在不同的系統環境中運行時,仍然能夠正確找到 Django 專案的主目錄。
BASE_DIR
的值是什麼?
假設你的 Django 專案結構如下:
myproject/
│── myproject/ # Django 核心應用
│ │── settings.py # 設定檔
│ │── urls.py
│ │── wsgi.py
│── manage.py
在這個情境下:
__file__
代表settings.py
檔案的 絕對路徑,例如:/home/user/myproject/myproject/settings.py
os.path.abspath(__file__)
會取得settings.py
的完整絕對路徑。os.path.dirname(...)
會獲取該檔案的 上一層目錄。os.path.dirname(os.path.dirname(...))
會再向上回溯一層,得到 Django 專案的根目錄。
最終,BASE_DIR
會變成:
/home/user/myproject
這就是 Django 專案的根目錄,所有與檔案路徑相關的設定,都可以基於這個變數來動態生成。
BASE_DIR
的工作原理
讓我們一步步拆解 BASE_DIR
這行程式碼的作用:
__file__
:獲取當前檔案的絕對路徑
在 Python 中,__file__
變數代表當前程式碼檔案的 完整路徑,例如:
print(__file__)
# 輸出: /home/user/myproject/myproject/settings.py
os.path.abspath(__file__)
:轉換為絕對路徑
os.path.abspath(__file__)
會確保 __file__
返回的值是 完整的絕對路徑:
print(os.path.abspath(__file__))
# 輸出: /home/user/myproject/myproject/settings.py
os.path.dirname(...)
:取得上一層目錄
這個函式會回到上一層目錄:
print(os.path.dirname(os.path.abspath(__file__)))
# 輸出: /home/user/myproject/myproject
os.path.dirname(os.path.dirname(...))
:再回上一層
再向上一層,我們就到達專案的根目錄:
print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# 輸出: /home/user/myproject
這就是 BASE_DIR
設定的核心邏輯!
BASE_DIR
的應用
設定 TEMPLATES
路徑
在 Django settings.py
中,我們可以使用 BASE_DIR
來動態設定模板的路徑:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
},
]
這樣 Django 會在 BASE_DIR/templates/
目錄下尋找模板檔案,而不需要寫死路徑。
設定 MEDIA
和 STATIC
資料夾
Django 專案通常會有 靜態檔案(Static Files) 和 媒體檔案(Media Files),可以這樣設定:
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
這樣,我們可以把靜態與媒體檔案放在 BASE_DIR
的子目錄內,讓 Django 可以正確找到它們。
設定 DATABASES
如果你使用 SQLite 作為資料庫,Django 會預設把資料庫檔案放在 BASE_DIR
下:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
這樣即使專案目錄搬移到不同的機器,SQLite 資料庫的路徑仍然能夠正確解析。
BASE_DIR
的替代方案
在 Python 早期,處理檔案和目錄路徑主要依賴 os
模組(如 os.path.join()
、os.path.abspath()
等)。
然而,從 Python 3.4 開始,引入了一個 更現代化且直覺的路徑處理模組——pathlib
。
相較於 os.path
,pathlib
提供了 物件導向的方式 來處理檔案與目錄路徑,使程式碼更加 簡潔、可讀性更高,並且能夠跨平台(Windows、Linux、MacOS)一致地運行。
為什麼要使用 pathlib
?
✅ 更直覺的語法
以往使用 os.path
處理路徑時,程式碼通常是這樣的:
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMPLATES_DIR = os.path.join(BASE_DIR, "templates")
而使用 pathlib
,我們可以寫得更簡潔:
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
TEMPLATES_DIR = BASE_DIR / "templates"
這樣的寫法 更具可讀性,也避免了 os.path.join()
的繁瑣語法。
pathlib
的核心概念
pathlib
的核心概念是 Path
類別,它代表 一個路徑物件,可以是 檔案 或 資料夾。
📌 創建 Path
物件
from pathlib import Path
# 創建一個代表目前目錄的 Path 物件
current_path = Path(".")
print(current_path.resolve()) # 顯示當前目錄的絕對路徑
# 指定某個檔案或資料夾
my_file = Path("/home/user/documents/myfile.txt")
print(my_file) # /home/user/documents/myfile.txt
pathlib
常見操作
✅ 1. 獲取當前工作目錄
from pathlib import Path
current_dir = Path.cwd() # 獲取當前工作目錄
print(current_dir) # 例如: /home/user/myproject
✅ 2. 取得專案根目錄 (BASE_DIR
替代 os.path
)
在 Django 專案中,我們通常用 BASE_DIR
來指示專案的根目錄:
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
print(BASE_DIR) # /home/user/myproject
這比 os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
更直覺。
✅ 3. 檢查檔案或資料夾是否存在
path = Path("example.txt")
# 檢查是否為檔案
print(path.is_file()) # True 或 False
# 檢查是否為資料夾
print(path.is_dir()) # True 或 False
# 檢查路徑是否存在
print(path.exists()) # True 或 False
✅ 4. 路徑拼接 (/
運算子)
在 pathlib
中,/
運算子可用於拼接路徑,這比 os.path.join()
更簡潔:
project_dir = Path("/home/user/myproject")
static_dir = project_dir / "static" # 自動拼接為 "/home/user/myproject/static"
print(static_dir)
✅ 5. 取得檔案名稱、目錄、後綴
file_path = Path("/home/user/documents/report.pdf")
# 取得檔案名稱(含副檔名)
print(file_path.name) # report.pdf
# 取得副檔名
print(file_path.suffix) # .pdf
# 取得檔案所在的目錄
print(file_path.parent) # /home/user/documents
# 取得純檔名(不含副檔名)
print(file_path.stem) # report
✅ 6. 建立新目錄
new_dir = Path("new_folder")
new_dir.mkdir(exist_ok=True) # exist_ok=True 避免報錯(如果目錄已存在)
✅ 7. 列出目錄內的檔案
folder = Path("/home/user/documents")
# 遍歷資料夾內的所有檔案與資料夾
for item in folder.iterdir():
print(item)
✅ 8. 讀取與寫入檔案
📌 讀取檔案內容
file_path = Path("example.txt")
# 讀取整個檔案內容
content = file_path.read_text()
print(content)
📌 寫入檔案
file_path.write_text("這是一個測試檔案!")
總結
✅ BASE_DIR
是 Django settings.py
中的重要變數,代表專案的根目錄。
✅ 它的核心邏輯是使用 os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
回溯到上一層目錄。
✅ BASE_DIR
讓我們可以使用相對路徑來設定模板、靜態檔案、媒體檔案、資料庫等,而不需要硬編碼絕對路徑。
✅ Python 3.6+ 可以使用 pathlib
來替代 os.path
,讓路徑操作更簡潔。
理解 BASE_DIR
之後,你可以更靈活地管理 Django 專案的路徑,讓程式碼更具可移植性!💡