【26.0】Django框架之settings源码
【一】Django配置文件介绍
- Django框架默认提供给我们一个配置文件
- 在我们项目根目录下的
setting.py
文件中,在里面我们可以看到很多的配置项 - 并且我们能够自主的添加相应的配置
- 但是其实这个文件只是Django暴露出来给我们的一个接口文件,在Django内部还存在一个更加强大的配置文件
# Django项目暴露出来,我们可以自主修改的配置文件
from 项目名 import settings
# Django内置的配置文件(用户不指定的前提下,使用默认的配置)
from django.conf import settings
【二】配置文件的优先级
- 当我们不对配置文件进行额外的配置修改时,项目会使用默认的配置文件
- 当我们在自定义的配置文件中修改了相关配置后,项目就会使用自定义的配置
# 比如 在项目目录下的配置文件中有一个配置项
# 这个配置的配置项含义是,当前项目所使用的语言为英文
# 在Django的后台登录上游很好的展现,我们看到的提示信息都是英文的
LANGUAGE_CODE = 'en-us'
# 但是其实在Django的默认配置文件中我们可以看到这个配置项还有很多其他的选择
# from django.conf.settings import global_settings
LANGUAGE_CODE = 'en-us'
# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
# Languages we provide translations for, out of the box.
LANGUAGES = [
('af', gettext_noop('Afrikaans')),
('ar', gettext_noop('Arabic')),
('ar-dz', gettext_noop('Algerian Arabic')),
('ast', gettext_noop('Asturian')),
('az', gettext_noop('Azerbaijani')),
('bg', gettext_noop('Bulgarian')),
('be', gettext_noop('Belarusian')),
('bn', gettext_noop('Bengali')),
('br', gettext_noop('Breton')),
('bs', gettext_noop('Bosnian')),
('ca', gettext_noop('Catalan')),
('cs', gettext_noop('Czech')),
('cy', gettext_noop('Welsh')),
('da', gettext_noop('Danish')),
('de', gettext_noop('German')),
('dsb', gettext_noop('Lower Sorbian')),
('el', gettext_noop('Greek')),
('en', gettext_noop('English')),
('en-au', gettext_noop('Australian English')),
('en-gb', gettext_noop('British English')),
('eo', gettext_noop('Esperanto')),
('es', gettext_noop('Spanish')),
('es-ar', gettext_noop('Argentinian Spanish')),
('es-co', gettext_noop('Colombian Spanish')),
('es-mx', gettext_noop('Mexican Spanish')),
('es-ni', gettext_noop('Nicaraguan Spanish')),
('es-ve', gettext_noop('Venezuelan Spanish')),
('et', gettext_noop('Estonian')),
('eu', gettext_noop('Basque')),
('fa', gettext_noop('Persian')),
('fi', gettext_noop('Finnish')),
('fr', gettext_noop('French')),
('fy', gettext_noop('Frisian')),
('ga', gettext_noop('Irish')),
('gd', gettext_noop('Scottish Gaelic')),
('gl', gettext_noop('Galician')),
('he', gettext_noop('Hebrew')),
('hi', gettext_noop('Hindi')),
('hr', gettext_noop('Croatian')),
('hsb', gettext_noop('Upper Sorbian')),
('hu', gettext_noop('Hungarian')),
('hy', gettext_noop('Armenian')),
('ia', gettext_noop('Interlingua')),
('id', gettext_noop('Indonesian')),
('ig', gettext_noop('Igbo')),
('io', gettext_noop('Ido')),
('is', gettext_noop('Icelandic')),
('it', gettext_noop('Italian')),
('ja', gettext_noop('Japanese')),
('ka', gettext_noop('Georgian')),
('kab', gettext_noop('Kabyle')),
('kk', gettext_noop('Kazakh')),
('km', gettext_noop('Khmer')),
('kn', gettext_noop('Kannada')),
('ko', gettext_noop('Korean')),
('ky', gettext_noop('Kyrgyz')),
('lb', gettext_noop('Luxembourgish')),
('lt', gettext_noop('Lithuanian')),
('lv', gettext_noop('Latvian')),
('mk', gettext_noop('Macedonian')),
('ml', gettext_noop('Malayalam')),
('mn', gettext_noop('Mongolian')),
('mr', gettext_noop('Marathi')),
('my', gettext_noop('Burmese')),
('nb', gettext_noop('Norwegian Bokmål')),
('ne', gettext_noop('Nepali')),
('nl', gettext_noop('Dutch')),
('nn', gettext_noop('Norwegian Nynorsk')),
('os', gettext_noop('Ossetic')),
('pa', gettext_noop('Punjabi')),
('pl', gettext_noop('Polish')),
('pt', gettext_noop('Portuguese')),
('pt-br', gettext_noop('Brazilian Portuguese')),
('ro', gettext_noop('Romanian')),
('ru', gettext_noop('Russian')),
('sk', gettext_noop('Slovak')),
('sl', gettext_noop('Slovenian')),
('sq', gettext_noop('Albanian')),
('sr', gettext_noop('Serbian')),
('sr-latn', gettext_noop('Serbian Latin')),
('sv', gettext_noop('Swedish')),
('sw', gettext_noop('Swahili')),
('ta', gettext_noop('Tamil')),
('te', gettext_noop('Telugu')),
('tg', gettext_noop('Tajik')),
('th', gettext_noop('Thai')),
('tk', gettext_noop('Turkmen')),
('tr', gettext_noop('Turkish')),
('tt', gettext_noop('Tatar')),
('udm', gettext_noop('Udmurt')),
('uk', gettext_noop('Ukrainian')),
('ur', gettext_noop('Urdu')),
('uz', gettext_noop('Uzbek')),
('vi', gettext_noop('Vietnamese')),
('zh-hans', gettext_noop('Simplified Chinese')),
('zh-hant', gettext_noop('Traditional Chinese')),
]
# 我们可以将默认的 en-us 替换成 zh-hans
# 这样我们在看到Django的提示信息的时候就会发现变成了简体中文
【三】配置文件的包含关系
- 在项目根目录下的配置文件存在的配置项,在项目的全局配置文件中肯定也有
- 但是在项目的全局配置文件中有的配置项,项目根目录下的配置文件未必有
【四】正确的配置文件使用
# 我们如果在Django项目的其他位置想要试用Django的配置文件,最正确的导入方式应该是
from django.conf import settings
# 这样导入的配置文件我们既可以使用自定义的,也可以使用全局默认的配置
【五】settings源码剖析
【1】入口
- 我们通过导入全局的配置文件,从全局的配置文件进入到源码中
from django.conf import settings
【2】settings
其实是一个对象
-
我们可以看到 在源码的最后一行是
settings = LazySettings()
-
也就是说,我们当前使用的 settings 其实是 LazySettings 类产生的一个对象
【3】剖析LazySettings
- 剖析源码时,我们应该只剖析我们想要的核心部分,而不是所有源码都进行解读
- 如果把所有源码都解读一遍,只会让我们的精力大大消耗掉
class LazySettings(LazyObject):
def _setup(self, name=None):
# 在这里我们可以看到 通过项目环境变量获取到了键为 ENVIRONMENT_VARIABLE 的值
# os.environ : 当前项目的环境变量
# ENVIRONMENT_VARIABLE : 在上面有
# ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
# DJANGO_SETTINGS_MODULE 在哪里能看到呢?,其实就是在我们项目文件 manage.py 中
# os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'BulletinBoardSystem.settings')
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))
# 将获取到的本地配置文件的路径传给 Settings 实例化得到一个对象
self._wrapped = Settings(settings_module)
manage.py
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'BulletinBoardSystem.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
【4】剖析Settings
class Settings:
def __init__(self, settings_module):
# settings_module : 是本地的项目配置文件路径
# settings_module : 项目名.settings.py
# 获取全局配置文件中所有的变量名
for setting in dir(global_settings):
# 校验变量名是否是全大写
# 这也是为什么在配置文件中所有的配置变量名都是大写的原因
if setting.isupper():
# 在配置文件变量名全大写的前提下,设置相应的属性
# setting : 当前配置的变量名
# getattr(global_settings, setting) : 在全局配置文件中反射出指定键对应的属性值
setattr(self, setting, getattr(global_settings, setting))
# 将当前项目根目录的配置文件地址添加到自己的属性中
self.SETTINGS_MODULE = settings_module
# 将配置文件路径导入成一个模块对象
mod = importlib.import_module(self.SETTINGS_MODULE)
# 声明配置变量名元祖
tuple_settings = (
"INSTALLED_APPS",
"TEMPLATE_DIRS",
"LOCALE_PATHS",
)
self._explicit_settings = set()
# 遍历当前项目根目录下的所有变量名
for setting in dir(mod):
# 判断变量名是否为大写
if setting.isupper():
# 获取到变量名对应的变量值
setting_value = getattr(mod, setting)
【六】案例
【1】自定义配置文件
conf.settings.py
SOME_NAME = "some_name"
SOME_PASSWORD = "some_password"
【2】根配置文件
lib.conf.global_settings.py
GLOBAL_NAME = "base_name"
GLOBAL_PASSWORD = "base_password"
lib.__init__.py
import os
import importlib
# 包初始化文件
# 导入全局配置文件
from lib.conf import global_settings
# 导入跟录下的配置文件
class Settings(object):
def __init__(self):
# 【一】设置全局变量名和变量值
# 【1】循环获取当前全局配置文件中所有的变量名
for name in dir(global_settings):
# 【2】判断变量名是否为大写
if name.isupper():
# 【3】设置全局变量名和变量值
setattr(self, name, getattr(global_settings, name))
# 【二】设置项目变量名和变量值
# 【1】获取得到当前模块路径
module_path = os.environ.get("PROJECT_MODAL_SETTINGS")
# 【2】获取得到当前模块对象
mod = importlib.import_module(module_path)
# 【3】遍历获取变量名设置值
for name in dir(mod):
if name.isupper():
setattr(self, name, getattr(mod, name))
settings = Settings()
【3】启动文件
start.py
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
if __name__ == '__main__':
# 设置当前根目录下的环境变量路径
os.environ.setdefault("PROJECT_MODAL_SETTINGS", "conf.settings")
from lib.conf import settings
print(settings.GLOBAL_NAME)
print(settings.SOME_NAME)
本文来自博客园,作者:Chimengmeng,转载请注明原文链接:https://www.cnblogs.com/dream-ze/p/18119657