• django settings实现原理及自定义项目settings配置


    基于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动态导入模块

  • 相关阅读:
    本博客主题设置
    .NET开源类库Nini手册(INI、XML、注册表的配置应用)-中文翻译
    service层的@Autowired 与@Override
    ajax传值时各参数意义
    序列化+继承
    KMP
    SpringBoot启动过程:
    Web三层架构及MVC
    SpringBoot注解意义及作用
    Syntax error on token "{", { expected after this token相关的错误
  • 原文地址:https://www.cnblogs.com/michealjy/p/11743260.html
Copyright © 2020-2023  润新知