Django源码笔记——settings加载

2017-01-12 09:56:03来源:oschina作者:张豪飞人点击



# settings对象
通常要获取settings的配置项时候都会通过from django.conf import settings获取。
settings是一个LazySettings实例对象,在django.conf的__init__.py下settings = LazySettings(),由于模块本身只执行一次所以这是一个单例(简单说就是你每次导入的settings都是同一个实例对象)
参考:[python单例](http://www.pythontab.com/html/2014/pythonhexinbiancheng_0811/846.html)
`class LazySettings(LazyObject)`
```python
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)`
```python
def new_method_proxy(func):
def inner(self, *args):
if self._wrapped is empty:
self._setup()
return func(self._wrapped, *args)
return inner
```
测试
```python
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)
```
```python
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
```

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台