django配置文件相关操作
django配置文件相关操作
1.django其实有两个配置文件
一个是暴露给用户可以自定义的基本配置
from 项目名 import settings
一个是全局的系统默认的配置(用户不指定的情况 采用的配置)
from django.conf import global_settings
2.用户如果在暴露给用户的配置文件中指定了配置则使用用户的 不指定则又会使用系统默认的
# 思考:如何实现上述操作(两个配置文件相互兼容) 一会儿需要看源码
"""测试配置文件的兼容性
其实django系统默认支持很多国家的语言 只需要修改配置即可
LANGUAGE_CODE = 'en-us'
系统配置文件中还提供了很多其他语言配置
"""
3.暴露给用户的配置文件中有的配置 系统配置文件中肯定有
暴露给用户的配置文件中没有的配置 系统配置文件中也有
4.我们在django中如果想要使用配置文件 那么最正确的导入方式
from django.conf import settings
# 思考:上述的settings既可以导入暴露给用户配置文件中的所有配置也可以导入系统默认的配置
django配置文件源码
看源码不要想着所有的代码都看懂 看核心即可
1.切入点:setting文件
将其导入
from django.conf import settings
Ctrl + 点击 settings 进入其中发现:
...
settings = LazySettings()
'''发现它是由 LazySettings 类实例的对象'''
2.再点击进入到 LazySettings 类中查看
class LazySettings(LazyObject):
def _setup(self, name=None):
# 获取暴露给用户的配置文件字符串路径 'day62_BBS.settings'
settings_module = os.environ.get(ENVIRONMENT_VARIABLE)
...
# 将上述字符串路径当做参数传给Settings类实例化
self._wrapped = Settings(settings_module)
...
settings = LazySettings()
3.再点击上面写的ENVIRONMENT_VARIABLE看看里面有啥
发现:
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
'''
翻译是Django的配置模板, Django在启动的时候就会加载这个配置, 我们再去Django的启动文件 manage.py 中去看看
'''
4.manage.py文件里的代码
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day62_BBS.settings")
将'DJANGO_SETTINGS_MODULE':'day62_BBS.settings'添加进环境变量配置大字典中
1.os.environ 可以看成是一个项目全局的大字典 任何地方都可以使用
2.django的入口文件是manage.py(也可以看成是启动文件)
3.os.environ.setdefault() 相当于给字典添加键值对
5.再返回到 LazySetting 类当中分析
class LazySettings(LazyObject):
def _setup(self, name=None):
# 这里相当于是 settings_module = 'day62_BBS.settings'
settings_module = os.environ.get(ENVIRONMENT_VARIABLE)
......
# 这里是将settings_module,也就是'day62_BBS.settings'传入到Settings类中实例化得到一个对象
self._wrapped = Settings(settings_module)
6.再点击进入 Settings 类中查看类代码
class Settings(object):
def __init__(self, settings_module):
# 获取系统配置文件中所有的变量名
for setting in dir(global_settings):
if setting.isupper(): # 校验变量名是否是纯大写(这就是为什么配置文件中的配置必须大写才能生效的原因)
setattr(self, setting, getattr(global_settings, setting))
'''通过反射获取系统配置文件中所有的大写变量名和对应的值 赋值给settings对象'''
self.SETTINGS_MODULE = settings_module
mod = importlib.import_module(self.SETTINGS_MODULE)
"""rom day62_BBS import settings """
# 循环获取暴露给用户的配置文件中所有的变量名
for setting in dir(mod):
if setting.isupper(): # 判断是否是纯大写
setting_value = getattr(mod, setting)
setattr(self, setting, setting_value) # 给对象设置属性
# 这里也就说明了为什么配置文件的变量名必须为大写的原因
通过 Settings 类的源码分析, 我们可以得出这样一个步骤 :
1.先得到全局配置文件中所有的大写的配置, 并将其加入到Settings类对象中去
2.然后再获取暴露给用户的settings配置中所有大写的值, 并将其也设置进Settings类对象中
3.上述两部操作之后,如果用户写了暴露给用户的配置文件中所有的变量名,那就用用户自己写的,如果没有就用global_settings里的配置
4.这样一来Settings类对象中如果第一次添加的配置名与第二次添加的配置名相同, 就会被第二次的配置覆盖
5.Django 启动加载的就是这个 Settings 类对象中所有的配置,
基于setting源码编程
学习了上面那个源码分析,自己来实现一下吧~~~
模拟一个暴露给用户的配置文件
conf
--settings.py
模拟一个系统内部默认配置文件
lib
--conf
----global_settings.py
详细代码
conf
'''--settings.py'''
NAME = '俺是暴露给用户自定义的NAME'
lib
--conf
'''----__init__.py'''
import importlib
import os
from lib.conf import global_settings
class Settings(object):
def __init__(self):
# 先循环获取全局配置文件中所有的名字
for name in dir(global_settings):
# print(name)
# 筛选出纯大写的配置
if name.isupper():
# print(name)
# 根据大写的名字获取对应的值
value = getattr(global_settings, name)
# 给对象设置键值对
setattr(self, name, value)
# 获取暴露给用户的自定义配置文件字符串路径
module_path_str = os.environ.get('aaa') # conf.settings
# print(module_path_str)
# 根据字符串路径导入模块
module_name = importlib.import_module(module_path_str)
for name in dir(module_name):
print(name)
if name.isupper():
value = getattr(module_name, name)
setattr(self, name, value)
settings = Settings()
'''----global_settings.py'''
NAME = '俺是系统默认的NAME'
PWD = '俺是系统默认的PWD'
age = '俺是系统默认的AGE'
HOBBY = '俺是系统默认的HOBBY'
'''start.py'''
import os
import sys
sys.path.append(os.path.dirname(__file__))
if __name__ == '__main__':
# 项目全局设置一个键值对
"""键可以随便写,值必须是暴露给用户的字符串路径"""
os.environ['aaa'] = 'conf.settings'
from lib.conf import settings
print(settings.NAME)
这样就是一个大致的流程,如果暴露给用户的变量名存在于模拟系统内部默认配置文件内,就会使用用户自己的配置信息,如果不在,则会使用默认配置文件里的配置信息