【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)

__EOF__

本文作者Chimengmeng
本文链接https://www.cnblogs.com/dream-ze/p/18119657.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @ 2024-04-07 18:29  Chimengmeng  阅读(57)  评论(0编辑  收藏  举报