今天仔細地追了一下前因後果, 發覺解法很簡單, 必須做兩件事:
- 設環境變數 DJANGO_SETTINGS_MODULE=APP.settings
- 要在載入 module 的路徑中加上 django project 的根目錄, 即放 APP 的位置
$ PYTHONPATH=.. DJANGO_SETTINGS_MODULE=APP.settings myscript.pymyscript.py 位在 project root。明白運作方式後, 做起來很簡單。
不設 DJANGO_SETTINGS_MODULE 的話會出現下面的 exception:
Traceback (most recent call last): File "/.../site-packages/django/db/__init__.py", line 14, in順著 traceback 看相關程式就會明白, django 會載入 DJANGO_SETTINGS_MODULE 作為整個 django 的設定檔。所以一定要設這變數, 而且載入 module 的路徑裡包念它的父目錄, 才能正確載入它。if not settings.DATABASES: File "/.../site-packages/django/utils/functional.py", line 276, in __getattr__ self._setup() File "/.../site-packages/django/conf/__init__.py", line 38, in _setup raise ImportError("Settings cannot be imported, because environment variable %s is undefined." % ENVIRONMENT_VARIABLE) ImportError: Settings cannot be imported, because environment variable DJANGO_SETTINGS_MODULE is undefined.
若不想在命令列加那兩個變數, 一個簡單的替代方案是參考 manage.py, 在程式裡先 import settings, 再執行 django.core.management.execute_manager(settings)。execute_manager 會從 settings 中取得相關路徑和 module 名稱, 用來設 DJANGO_SETTINGS_MODULE 和在 sys.path 中附加 settings 的父目錄。
不明白為啥要用這種繞彎的方式設定環境, 也許和 django 的載入和執行模組的設計哲學有關。附帶一提, django 裡有太多 lazy initialization, 增加讀程式碼的難度, 令人有點困擾。
沒有留言:
張貼留言