本文為 資料庫正規化 基本介紹系列文,第 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/myprojectBASE_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.pyos.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.pyos.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 專案的路徑,讓程式碼更具可移植性!💡