🍖Django之settings源码分析

引入

查看源码前提 :

  • 刚开始阅读一些库的源码的时候, 最好选一些代码量少的先感受一下
  • 碰到看不懂的, 我们没必要去死磕, 只看自己能看懂的, 看不懂的忽略

一.django的两个配置文件

  • 一个是暴露给用户可以自定义的配置文件 : 项目根目录下的setting.py文件
  • 一个是项目默认的配置文件 : 当用户不做任何配置的时候自动加载默认配置

二.分析源码解决疑问

  • 为什么配置文件必须是大写
  • 为什么当前用户配置了就使用用户配置的, 不配置就使用默认的

三.源码分析

1.突破口 : settings 文件,将其导入

from django.conf import settings

2.Ctrl + 点击 settings 进入其中

......
settings = LazySettings()

发现它是由 LazySettings 类实例的对象

3.再点击进入到 LazySettings 类中查看

class LazySettings(LazyObject):
    def _setup(self, name=None):
        # os.environ获取环境变量中所有的配置,相当于一个大字典,这里取出ENVIRONMENT_VARIABLE
        settings_module = os.environ.get(ENVIRONMENT_VARIABLE)
        if not settings_module:
        ......
        self._wrapped = Settings(settings_module)

4.我们先点击 ENVIRONMENT_VARIABLE 进去看看这是个什么

ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"

翻译是Django的配置模板, Django在启动的时候就会加载这个配置, 我们再去Django的启动文件 manage.py 中去看看

5.进入 manage.py 文件查看相关内容

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')

找到这一条, 将'DJANGO_SETTINGS_MODULE':'mysite.settings' 添加进环境变量配置大字典中

6.返回到 LazySetting 类当中分析

class LazySettings(LazyObject):
    def _setup(self, name=None):
        # 这里相当于是 settings_module = 'mysite.settings'
        settings_module = os.environ.get(ENVIRONMENT_VARIABLE)
        ......
        # 这里是将settings_module,也就是'mysite.settings'传入到Settings类中实例化得到一个对象
        self._wrapped = Settings(settings_module)

7.我们再点击进入 Settings 类中查看类代码

from django.conf import global_settings

class Settings:
    def __init__(self, settings_module):
        # update this dict from global settings (but only for ALL_CAPS settings)
        # 上面的提示是从全局配置中更新此字典(仅针对所有大写的配置),那么我们可以知道global_setting是一个全局配置文件
        for setting in dir(global_settings):
            if setting.isupper():
                setattr(self, setting, getattr(global_settings, setting))
                ......

8.点击 global_settings 进入全局配置文件中查看配置

"""
Default Django settings. Override these with settings in the module pointed to
by the DJANGO_SETTINGS_MODULE environment variable.
"""
# 默认的Django设置,用Django settings模块环境变量指向的模块中的设置覆盖这些设置
# 意思就是说这是默认的配置文件, 如果你在暴露给用户的settings文件中配置了某变量则覆盖这里面的变量

9.我们再返回 Settings 类分析其代码

class Settings(object):
    def __init__(self, settings_module):  # 'mysite.settings'
        # dir()获取全局配置文件里面所有的变量名,循环取出来
        for setting in dir(global_settings):  
            if setting.isupper():  # 校验是否是纯大写(这也就是配置变量小写无效)
                # getattr()获取全局变量中所有的大写配置的值
                # setattr()再将该配置名以及对应的值添加到Settings对象中
                setattr(self, setting, getattr(global_settings, setting))
        
        # 将'mysite.settings'赋值给self.SETTINGS_MODULE后面使用
        self.SETTINGS_MODULE = settings_module
        # importlib模块:以字符串的方式导入模块,也就导入了暴露给用户的配置文件
        # from mysite import settings
        mod = importlib.import_module(self.SETTINGS_MODULE)
        for setting in dir(mod):
            if setting.isupper():
                # 循环取出暴露给用户配置文件中的所有大写的配置值
                setting_value = getattr(mod, setting)
                .......
                # 然后再将其设置进入Settings对象中,有就覆盖,没有就添加
                setattr(self, setting, setting_value)

通过 Settings 类的源码分析, 我们可以得出这样一个步骤 :

  • 先得到全局配置文件中所有的大写的配置, 并将其加入到 Settings类对象中去
  • 然后再获取暴露给用户的 settings 配置中所有大写的值, 并将其也设置进 Settings 类对象中
  • 这样一来 Settings 类对象中如果第一次添加的配置名与第二次添加的配置名相同, 就会被第二次的配置覆盖
  • Django 启动加载的就是这个 Settings 类对象中所有的配置,
原文地址:https://www.cnblogs.com/songhaixing/p/14588907.html