Django的配置是在什么时候加载的?
之前一直没仔细看过这部分,昨天仔细看了下,今天做一记录:
**先说结论:**基本上可以理解为,配置文件在执行from django.conf import settings
时还没有加载,首次尝试查看或调用settings实例的属性(也就是配置文件内容时),才会被加载至settings中,也就是一种懒加载的模式。
关键点:
- LazySettings 实现一个
_setup(self, name=None)
覆盖父类同名方法来加载配置文件
主要分如下几步:
- 实例化
LazySettings
- 调用父类
__init__
方法 - 当调用
__getattr__
或者__dir__
等相关调用或查看实例属性的方法时,就会执行LazySettings中的_setup
方法加载配置
没有说的特别详细,但关键点就在上面。
Django代码部分:
以下为LazySettings所在文件:
关键在于继承的父类LazyObject
,实现的_setup
方法,及覆写的__getattr__
方法
"""
Settings and configuration for Django.
Values will be read from the module specified by the DJANGO_SETTINGS_MODULE environment
variable, and then from django.conf.global_settings; see the global settings file for
a list of all possible variables.
"""
import importlib
import os
import time # Needed for Windows
import warnings
from django.conf import global_settings
from django.core.exceptions import ImproperlyConfigured
from django.utils.deprecation import RemovedInDjango110Warning
from django.utils.functional import LazyObject, empty
from django.utils import six
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
class LazySettings(LazyObject):
"""
A lazy proxy for either global Django settings or a custom settings object.
The user can manually configure settings prior to using them. Otherwise,
Django uses the settings module pointed to by DJANGO_SETTINGS_MODULE.
"""
def _setup(self, name=None):
"""
Load the settings module pointed to by the environment variable. This
is used the first time we need any settings at all, if the user has not
previously configured the settings manually.
"""
settings_module = os.environ.get(ENVIRONMENT_VARIABLE)
if not settings_module:
desc = ("setting %s" % name) if name else "settings"
raise ImproperlyConfigured(
"Requested %s, but settings are not configured. "
"You must either define the environment variable %s "
"or call settings.configure() before accessing settings."
% (desc, ENVIRONMENT_VARIABLE))
self._wrapped = Settings(settings_module)
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):
"""
Called to manually configure the settings. The 'default_settings'
parameter sets where to retrieve any unspecified values from (its
argument must support attribute access (__getattr__)).
"""
if self._wrapped is not empty:
raise RuntimeError('Settings already configured.')
holder = UserSettingsHolder(default_settings)
for name, value in options.items():
setattr(holder, name, value)
self._wrapped = holder
@property
def configured(self):
"""
Returns True if the settings have already been configured.
"""
return self._wrapped is not empty