基于django 中的settings实现原理,实现自己项目配置文件的可插拔式设计

##首先说一下django中settings.py中的实现原理
'''
应该明确一点,django暴露给用户一个自定义配置的文件,即settings.py,用户配置了就是优先使用用户配置的,否则就使用默认的(from django.conf import global_settings) 同时配置文件中的变量名必须是大写的才能生效(显然,内部实现原理一定有判断是否大写)
'''
'''
其次是它的原理,通过from django.conf import settings 进入源码发现,是通过实例化生成一个LazySettings对象(这里面用到了单例模式,下面会详细介绍),再进源码,看到过程如下: 1.先通过环境变量名,拿到manage.py文件中一启动就写进大字典(相当于一个环境变量的全集合)里的settings文件名(字符串形式的)
2.先判断环境变量是否为空,空的话就抛异常,否则进入settings类中执行
3.执行过程就是用到dir,先循环global_settings中的各种属性方法,然后把其中大写的变量名(字符串)筛选出来,再通过反射的方式先从global_settings中取出值,再setattr到当前对象中
4.然后又通过importlib导入暴露给用户的settings文件,得到对象,同样的道理,先循环取出文件里的属性和方法,再判断是大写就反射取值
5.多了一步就是是否按格式写了(必须是元组或者列表)
6.然后反射设置值,这样,有的话就覆盖,没有就用默认的。 ''' ##然后讲一下用到到几个技术点: ''' 1.单例模式:settings本质就是实例化产生一个对象,但是每次运行都要开辟内存空间存放环境配置太耗资源了,就想到通过实例化一次settings对象,下次用的时候直接导入模块就好了。 2.dir:目的是把对象中的属性和方法全部取出来,列表的形式展示。扩展:dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息。 3.反射:主要的语句就是setattr(self, a, getattr(b, c)), 意思就是,先通过c字符串在b对象中取出对应的值,然后把该值赋值给当前对象的a方法或者属性,即self.a = getattr(b,c). 反射主要用在通过字符串判断、取值、设置及删除对象中的方法或者属性。 4.importlib.import_module('settings') == import settings 前者是动态导入,可以根据前一句得到的字符串进行导入,常用场景是希望从配置文件等地获取要被动态加载的module,但配置项通常为字符串类型,无法用import加载。 具体见页尾连接
''' ## 最后思路讲完了,话不多说,直接上代码
'''
还是要先说两句,先设置全局变量,给个启动文件,然后再暴露一个配置文件让用户写。
''' #conf
#里面有暴露给用户的settings.py NAME = "我是暴露给用户的自定义配置" #lib(全局变量就在这里)
## conf(是一个包) ### __init__.py
'''
导入一个模块时,会执行这个模块的代码,申请内存空间,把变量放到内存空间中,导入这个包,会执行__init__中的代码
''' import os
import importlib
from lib.conf import global_settings class Settings(object):
def __init__(self):
for setting in dir(global_settings):
if setting.isupper():
k = setting
v = getattr(global_settings,setting)
setattr(self,k,v)
# 从全局的大字典中获取到暴露给用户的配置文件字符串路径
mod = os.environ.get('xxx')
# mod = 'conf.settings'
module = importlib.import_module(mod)
"""
from conf import settings
module 》》》 settings
"""
for setting in dir(module):
if setting.isupper():
k = setting
v = getattr(module,setting)
setattr(self,k,v) # 循环获取默认的配置文件中所有的大写配置
# 利用setattr给对象不停的设置键值对
# 再循环获取暴露给用户的自定义配置文件中所有的大写的配置
# 再利用setattr给对象不停的设置键值对 settings = Settings() ### global_settings.py NAME = '我是系统默认的全局配置' #start.py import os
import sys BASE_DIR = os.path.dirname(__file__)
sys.path.append(BASE_DIR) os.environ.setdefault('xxx','conf.settings')
from lib.conf import settings
print(settings.NAME) ## 运行后会打印 "我是暴露给用户的自定义配置"

importlib动态导入模块

最新文章

  1. NFC OMA 访问
  2. React Native 的高度与宽度设置
  3. C#POP3协议实现SSL验证登陆GMAIL
  4. apache commons-email1.3使用
  5. pku3670 Eating Together
  6. route命令详解与使用实例
  7. libusb-win32 在visual studio2008中成功编译回忆录
  8. Eclipse 浏览文件插件- OpenExplorer
  9. linux 环境操作faq 记录
  10. Week4(9月30日):
  11. DELPHI 通過窗口句柄或窗口标题得到进程句柄
  12. HDU 5776 sum
  13. Swift4 Json
  14. Jenkins: 配置信息变更历史
  15. 【深度学习】keras + tensorflow 实现猫和狗图像分类
  16. android smartbar适配
  17. Spark环境搭建(五)-----------Spark生态圈概述与Hadoop对比
  18. ovs之组网实验
  19. windows下面配合thinkphp5.1.7的nginx.conf内容
  20. Microsoft Windows .Reg File Dialog Box Message Spoofing 0day

热门文章

  1. 【CF525E】Anya and Cubes(meet in middle)
  2. A1029 Median (25 分)
  3. 一种单机支持 JavaWeb 容器万级并发的设想
  4. 领域驱动设计(DDD)编码实践
  5. 网络流 之 dinic 算法
  6. Eureka注册中心的自我保护模式
  7. 传统码头建设企业:Azure DevOps Server 流水线技术沟通
  8. (四十二)golang--协程之间通信的方式
  9. multer 基础教程(英文版)
  10. 配置每次git push 不需要输入账号密码