settings对象
通常要获取settings的配置项时候都会通过from django.conf import settings获取。
settings是一个LazySettings实例对象,在django.conf的__init__.py下settings = LazySettings(),由于模块本身只执行一次所以这是一个单例(简单说就是你每次导入的settings都是同一个实例对象)
参考:
class LazySettings(LazyObject)
class LazySettings(LazyObject): def _setup(self, name=None): # 根据配置的settings文件导入配置 settings_module = os.environ.get(ENVIRONMENT_VARIABLE) pass self._wrapped = Settings(settings_module) # 和下面的UserSettingsHolder一样都是BaseSettings子类 def __getattr__(self, name): # 获取属性时候没有导入配置则导入 if self._wrapped is empty: self._setup(name) return getattr(self._wrapped, name) def configure(self, default_settings=global_settings, **options): # 手动自定义配置,没有配置才能使用 if self._wrapped is not empty: raise RuntimeError('Settings already configured.') holder = UserSettingsHolder(default_settings) # 和上面的Settings一样都是BaseSettings子类 for name, value in options.items(): setattr(holder, name, value) self._wrapped = holder @property def configured(self): return self._wrapped is not empty
父类LazyObject中很多类似__getattr__ = new_method_proxy(getattr)
的使用,没有配置时候先导入配置 ,然后获取self._wrapped配置中的信息和属性
相当于:__getattr__ = getattr(self,_wrapped, *args)
def new_method_proxy(func): def inner(self, *args): if self._wrapped is empty: self._setup() return func(self._wrapped, *args) return inner
测试
In [7]: dir(settings)Out[7]:['ABSOLUTE_URL_OVERRIDES', 'ADMINS', 'ALLOWED_HOSTS', 'ALLOWED_INCLUDE_ROOTS',# 省略...
总结:LazySettings主要用于控制配置文件的来源
class Settings
实际上配置文件的配置都在Settings中, 配置文件中的配置(必须全部大写)都添加为Settings实例的属性。UserSettingsHolder中配置都在LazySettings中手动循环添加,这里不在赘述,下面只看Settings导入配置过程
class BaseSettings(object): """ Common logic for settings whether set by a module or by the user. """ def __setattr__(self, name, value): # "MEDIA_URL", "STATIC_URL"两项配置必须以"/"结尾 if name in ("MEDIA_URL", "STATIC_URL") and value and not value.endswith('/'): raise ImproperlyConfigured("If set, %s must end with a slash" % name) object.__setattr__(self, name, value)
class Settings(BaseSettings): def __init__(self, settings_module): # 配置项必须为全大写 for setting in dir(global_settings): # 导入默认配置文件的配置,即初始化配置 if setting.isupper(): setattr(self, setting, getattr(global_settings, setting)) # store the settings module in case someone later cares self.SETTINGS_MODULE = settings_module mod = importlib.import_module(self.SETTINGS_MODULE) # import指定的配置文件 self._explicit_settings = set() for setting in dir(mod): # 导入配置指定配置文件中的配置项覆盖默认配置 if setting.isupper(): setting_value = getattr(mod, setting) pass setattr(self, setting, setting_value) self._explicit_settings.add(setting) pass def is_overridden(self, setting): return setting in self._explicit_settings
现在settings中已经有所有的配置项
conf包
|- conf|--- app_template # app目录模板:manage.py startapp|--- locale # 语言包和对应时间表示格式|--- project_template # app项目模板 :manage.py startproject|--- urls