使用
應從django模塊引入配置:
from django.conf import settings
而不是直接從項目文件中引入
from proj import settings
直接從項目文件中引入會破壞app的獨立性。比如我想要把proj項目中的支付模塊pay_app分離出去,就要修改所有pay_app中直接從proj項目配置文件中引入配置的語句
注意,django.conf.settings不是一個模塊,而是一個對象。 所以不可以單獨導入每個配置項:
from django.conf.settings import DEBUG # 這是錯誤的做法
指定配置文件
在Django啟動時需要制定配置文件,也就是給環境變量DJANGO_SETTINGS_MODULE賦值
# 萬物起源:manage.py
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings")
LazySettings
from django.conf import settings
實際上是引入了LazySettings類的一個實例,這是一個單例模式,每次導入的settings都是同一個實例對象
# django/conf/__init__.py
class LazySettings(LazyObject):
...
settings = LazySettings()
LazySettings繼承自LazyObject,它會以懶加載的機制去讀取配置,獲取某個屬性的當下才會去加載
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
class LazySettings(LazyObject):
def _setup(self, name=None):
# 從環境變量DJANGO_SETTINGS_MODULE中獲取配置文件位置
settings_module = os.environ.get(ENVIRONMENT_VARIABLE)
# 真正讀取配置的對象是Settings的實例
self._wrapped = Settings(settings_module)
def __getattr__(self, name):
# 實例化settings后,settings被訪問前,settings._wrapped為空對象
if self._wrapped is empty:
# 訪問settings的屬性,即調用__getattr__時才回去加載配置
self._setup(name)
val = getattr(self._wrapped, name)
# 訪問對象的屬性時會先在 __dict__ 中查找
# 沒有找到,才會去調用 __getattr__ 方法
# 因此這里使用self.__dict__做了緩存
self.__dict__[name] = val
return val
empty = object()
class LazyObject(object):
_wrapped = None
def __init__(self):
self._wrapped = empty
LazySettingss主要用於控制配置文件的來源,並實現了懶加載的機制,真正讀取配置的對象是Settings的實例
Settings
from django.conf import global_settings
class Settings(object):
def __init__(self, settings_module):
# global_settings 中是Django的默認配置
for setting in dir(global_settings):
if setting.isupper():
# 先加載Django的默認配置
setattr(self, setting, getattr(global_settings, setting))
self.SETTINGS_MODULE = settings_module
# 載入項目配置
mod = importlib.import_module(self.SETTINGS_MODULE)
for setting in dir(mod):
# 只會載入項目配置文件中全部大寫的 KEY
# 因此,如果選擇用django.conf導入配置,配置的KEY必須要全部大寫
# 如果直接從配置文件導入就沒有這個限制了
if setting.isupper():
setting_value = getattr(mod, setting)
# 項目配置會覆蓋Django的默認配置
# 相當於 self.__dict__[setting] = setting_value
setattr(self, setting, setting_value)