咱們在django項目中,新建一個app的時候,都會有一個setting.py文件,裏面包含了整個項目全部的配置,包括apps,中間鍵,數據庫等等,django是如何將該setting文件利用起來的呢。數據庫
(1)啓動的時候,指定默認的配置文件django
django在啓動的時候,會調用manage.py文件運行server的實例,在文件一開始的時候,manage.py會調用下面代碼app
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djtest.settings")
設置默認的配置文件的環境變量DJANGO_SETTINGS_MODULE,該環境變量的名稱,定義在django/conf/_init.py文件裏面less
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
(2)根據配置文件裏面的配置項,提取到django/conf/_init.py裏面的Setting類裏面this
過程主要包含兩步spa
1. 根據DJANGO_SETTINGS_MODULE指定的配置文件調用mod = importlib.import_module(self.SETTINGS_MODULE),將該模塊importcode
2. 調用for setting in dir(mod) 遍歷該mod的屬性,將全部的大寫的配置屬性,提出取來,利用setattr(self, setting, setting_value),保存爲本身的屬性。server
class Settings(BaseSettings): def __init__(self, settings_module): # update this dict from global settings (but only for ALL_CAPS settings) 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 try: # 根據 manage.py 中的os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djtest.settings"),設置的配置文件,import該配置文件 mod = importlib.import_module(self.SETTINGS_MODULE) except ImportError as e: raise ImportError( "Could not import settings '%s' (Is it on sys.path? Is there an import error in the settings file?): %s" % (self.SETTINGS_MODULE, e) ) tuple_settings = ("INSTALLED_APPS", "TEMPLATE_DIRS") # setting文件裏面顯示申明的屬性集合,是個set類型的,是個集合 self._explicit_settings = set() # dir(object)返回object的屬性方法列表,所以,這裏dir會返回setting文件裏面的全部等號左邊的屬性 for setting in dir(mod): if setting.isupper(): setting_value = getattr(mod, setting) if (setting in tuple_settings and isinstance(setting_value, six.string_types)): raise ImproperlyConfigured("The %s setting must be a tuple. " "Please fix your settings." % setting) # 將setting文件裏面的全部屬性提出來,放到這個Setting類裏面來 setattr(self, setting, setting_value) self._explicit_settings.add(setting) if not self.SECRET_KEY: raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.") if hasattr(time, 'tzset') and self.TIME_ZONE: # When we can, attempt to validate the timezone. If we can't find # this file, no check happens and it's harmless. zoneinfo_root = '/usr/share/zoneinfo' if (os.path.exists(zoneinfo_root) and not os.path.exists(os.path.join(zoneinfo_root, *(self.TIME_ZONE.split('/'))))): raise ValueError("Incorrect timezone setting: %s" % self.TIME_ZONE) # Move the time zone info into os.environ. See ticket #2315 for why # we don't do this unconditionally (breaks Windows). os.environ['TZ'] = self.TIME_ZONE time.tzset() def is_overridden(self, setting): return setting in self._explicit_settings
(3)django的其餘模塊在使用配置文件裏面的配置項的時候,就是從Setting類中獲取,而不從配置文件直接獲取。blog