Django之settings源码分析
引入
查看源码的前提
- 刚开始阅读一些库的源码的时候,最好选一些代码量少的先感受一下
- 看到看不懂的,没有必要去死磕,挑一些看得懂的,再结合网上的一些文献
一.django 的两个配置文件
- 一个是暴露给用户可以自己自定义的配置文件也就是项目根目录下的
settings.py
- 一个是项目默认的配置文件:当用户不做任何配置的时候自动加载默认配置
二.分析源码解决疑问
- 为什么配置文件必须是大写
- 为什么当前用户配置了就是用用户配置的参数,没有配置就选择默认的参数
三.源码分析
1.突破口:settings文件
- 我们可以手动导入settings文件,然后点进去看看到底是怎么回事
from django.conf import settings
2.Ctrl + 点击进入settings文件
- 映入眼帘的就是
settings = LazySettings()
- 可以发现settings是由LazySettings()实例化的对象
3.进入到LazySettings()类去看看怎么个事
settings_module = os.environ.get(ENVIRONMENT_VARIABLE)
- 可以看到这一行代码,
os.environ
是获取到当前环境变量的所有配置,它的形式是一个字典 - 所以这行代码的意思就是从这个配置大字典里面取出键为
ENVIRONMENT_VARIABLE
的值
4.进入到ENVIRONMENT_VARIABLE看看啥情况
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
- 这段字符串翻译过来就是django的配置模板,当django启动的时候就会加载这个配置,所以我们再去启动文件manage.py去查看一下
5.进入到manage.py一探究竟
os.environ.setdefault('DJANGO_SETTINGS_MODULE','pythonProjecttestmid.settings')
- 不难解读出,这段代码的意思是给当前环境变量这个大字典的
DJANGO_SETTINGS_MODULE
设置一个默认值为pythonProjecttestmid
6.返回到LazySettings()类继续往下看
self._wrapped = Settings(settings_module)
- 可以看到它将在manage.py里往环境变量塞进去的值给了
Settings()
这个类,实例化得到一个对象
7.进到Settings()
这个类看一看
# 这个循环将global_settings这个全局配置的文件遍历了一遍
for setting in dir(global_settings):
# 如果是大写的名称
if setting.isupper():
# 就将全局配置文件的内容加到当前这个对象
setattr(self, setting, getattr(global_settings, setting))
# 将根目录下的配置文件路径赋值给SETTINGS_MODULE
self.SETTINGS_MODULE = settings_module
# 用importlib模块,以字符串的形式导入根目录下的配置文件
mod = importlib.import_module(self.SETTINGS_MODULE)
# 根据以上分析,大概可以推算出接下来要对mod做手脚,此时mod就是项目根目录下的配置文件对象
# 这一点我认为需要搞清楚
8.继续往下看,看有没有关于mod的内容
# 跟之前的套路一样 遍历根目录下的配置文件
for setting in dir(mod):
# 如果名称是大写
if setting.isupper():
# 就将它的值赋给 setting_value
setting_value = getattr(mod, setting)
... # 这里看不懂的就省略了
# 再将setting_value赋值给settings对象,也就是最开始导入的那个settings
setattr(self, setting, setting_value)
self._explicit_settings.add(setting)
四.总结
通过Settings类的源码分析,我们可以得出这样一个步骤:
-
先得到全局全局配置文件中所有的大写配置,然后通过一些方法将其加入到settings对象里面
-
再得到根目录下的所有的大写配置,再将他也加入到settings对象里面
-
这样就可以做到让根目录下的配置覆盖默认配置