Django加载配置的过程详解

 更新时间:2022年05月12日 15:57:13   作者:托塔天王李  
这篇文章主要介绍了Django加载配置的过程详解,包括Django服务启动 manage.py的详细介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

一. Django服务启动 manage.py

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ui.settings")
设置配置文件环境变量-
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ui.settings")
    try:
        from django.core.management import execute_from_command_line
    except ImportError:
        # The above import may fail for some other reason. Ensure that the
        # issue is really that Django is missing to avoid masking other
        # exceptions on Python 2.
        try:
            import django
        except ImportError:
            raise ImportError(
                "Couldn't import Django. Are you sure it's installed and "
                "available on your PYTHONPATH environment variable? Did you "
                "forget to activate a virtual environment?"
            )
        raise
    execute_from_command_line(sys.argv)

二. 引入配置

django/core/management/init.py文件中引入配置

from django.conf import settings

django/conf/init.py配置文件源码

from django.utils.functional import LazyObject, empty
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
class LazySettings(LazyObject):
    """
    A lazy proxy for either global Django settings or a custom settings object.
    The user can manually configure settings prior to using them. Otherwise,
    Django uses the settings module pointed to by DJANGO_SETTINGS_MODULE.
    """
    def _setup(self, name=None):
        """
        Load the settings module pointed to by the environment variable. This
        is used the first time we need any settings at all, if the user has not
        previously configured the settings manually.
        """
        settings_module = os.environ.get(ENVIRONMENT_VARIABLE)
        if not settings_module:
            desc = ("setting %s" % name) if name else "settings"
            raise ImproperlyConfigured(
                "Requested %s, but settings are not configured. "
                "You must either define the environment variable %s "
                "or call settings.configure() before accessing settings."
                % (desc, ENVIRONMENT_VARIABLE))
        self._wrapped = Settings(settings_module)
    def __repr__(self):
        # Hardcode the class name as otherwise it yields 'Settings'.
        if self._wrapped is empty:
            return '<LazySettings [Unevaluated]>'
        return '<LazySettings "%(settings_module)s">' % {
            'settings_module': self._wrapped.SETTINGS_MODULE,
        }
    def __getattr__(self, name):
        """
        Return the value of a setting and cache it in self.__dict__.
        """
        if self._wrapped is empty:
            self._setup(name)
        val = getattr(self._wrapped, name)
        self.__dict__[name] = val
        return val
    def __setattr__(self, name, value):
        """
        Set the value of setting. Clear all cached values if _wrapped changes
        (@override_settings does this) or clear single values when set.
        """
        if name == '_wrapped':
            self.__dict__.clear()
        else:
            self.__dict__.pop(name, None)
        super(LazySettings, self).__setattr__(name, value)
    def __delattr__(self, name):
        """
        Delete a setting and clear it from cache if needed.
        """
        super(LazySettings, self).__delattr__(name)
        self.__dict__.pop(name, None)
    def configure(self, default_settings=global_settings, **options):
        """
        Called to manually configure the settings. The 'default_settings'
        parameter sets where to retrieve any unspecified values from (its
        argument must support attribute access (__getattr__)).
        """
        if self._wrapped is not empty:
            raise RuntimeError('Settings already configured.')
        holder = UserSettingsHolder(default_settings)
        for name, value in options.items():
            setattr(holder, name, value)
        self._wrapped = holder
    @property
    def configured(self):
        """
        Returns True if the settings have already been configured.
        """
        return self._wrapped is not empty
settings = LazySettings() # 单例模式 

LazySettings()惰性加载是一种延迟计算的技术,当只有真正需要使用结果的时候才会去计算。Django提供了两种惰性加载模块,分别是lazy和LazyObject,前者主要针对可以调用的对象,延迟函数的调用;后者针对类,延迟类的实例化。

如果想要让某个类有延迟实例化的功能,必须做两件事情:

1)继承LazyObject;
2)实现_setup方法。

empty = object()
def new_method_proxy(func):
    def inner(self, *args):
        if self._wrapped is empty:
            self._setup()
        return func(self._wrapped, *args)
    return inner
class LazyObject(object):
    """
    A wrapper for another class that can be used to delay instantiation of the
    wrapped class.
    By subclassing, you have the opportunity to intercept and alter the
    instantiation. If you don't need to do that, use SimpleLazyObject.
    """
    # Avoid infinite recursion when tracing __init__ (#19456).
    _wrapped = None
    def __init__(self):
    	"""
    	初始化
    	"""
        # Note: if a subclass overrides __init__(), it will likely need to
        # override __copy__() and __deepcopy__() as well.
        self._wrapped = empty
    __getattr__ = new_method_proxy(getattr)
    def __setattr__(self, name, value):
        if name == "_wrapped":
            # Assign to __dict__ to avoid infinite __setattr__ loops.
            self.__dict__["_wrapped"] = value
        else:
            if self._wrapped is empty:
                self._setup()
            setattr(self._wrapped, name, value)
    def __delattr__(self, name):
        if name == "_wrapped":
            raise TypeError("can't delete _wrapped.")
        if self._wrapped is empty:
            self._setup()
        delattr(self._wrapped, name)
    def _setup(self):
        """
        Must be implemented by subclasses to initialize the wrapped object.
        """
        raise NotImplementedError('subclasses of LazyObject must provide a _setup() method')
    def __reduce__(self):
        if self._wrapped is empty:
            self._setup()
        return (unpickle_lazyobject, (self._wrapped,))
    def __getstate__(self):
        if self._wrapped is empty:
            self._setup()
        return self._wrapped.__dict__

三. 加载配置

ManagementUtility 的execute方法的 settings.INSTALLED_APPS

1) settings.INSTALLED_APPS 因为settings没有INSTALLED_APPS属性就会调用LazySettings的__getattr__方法

    def __getattr__(self, name):
        """
        Return the value of a setting and cache it in self.__dict__.
        """
        if self._wrapped is empty:
            self._setup(name)
        val = getattr(self._wrapped, name)
        self.__dict__[name] = val
        return val

2)self._wrapped is empty(empty是LazyObject的类属性)为True, 就会执行LazySettings的_setup方法,实例self._wrapped =Settings(settings_module)

    def _setup(self, name=None):
        """
        Load the settings module pointed to by the environment variable. This
        is used the first time we need any settings at all, if the user has not
        previously configured the settings manually.
        """
        settings_module = os.environ.get(ENVIRONMENT_VARIABLE)
        if not settings_module:
            desc = ("setting %s" % name) if name else "settings"
            raise ImproperlyConfigured(
                "Requested %s, but settings are not configured. "
                "You must either define the environment variable %s "
                "or call settings.configure() before accessing settings."
                % (desc, ENVIRONMENT_VARIABLE))
        self._wrapped = Settings(settings_module)

3) 后面再访问属性时直接从self._wrapped.dict(settings.wrapped.dict)中获取

到此这篇关于Django加载配置的过程详解的文章就介绍到这了,更多相关django加载配置内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 解决python脚本中error: unrecognized arguments: True错误

    解决python脚本中error: unrecognized arguments: True错误

    这篇文章主要介绍了解决python脚本中error: unrecognized arguments: True错误,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-04-04
  • Python 查看文件的读写权限方法

    Python 查看文件的读写权限方法

    下面小编就为大家分享一篇Python 查看文件的读写权限方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-01-01
  • 一起来了解python的运算符

    一起来了解python的运算符

    这篇文章主要为大家详细介绍了python的运算符,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-01-01
  • python 测试实现方法

    python 测试实现方法

    使用python进行测试也足够简明了
    2008-12-12
  • python浅析守护线程与非守护线程的区别与使用

    python浅析守护线程与非守护线程的区别与使用

    守护线程,又称后台线程,它是在后台运行的,如果所有前台线程都死亡,那么后台线程就会自动死亡,本章我们来了解守护线程与非守护线程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-08-08
  • Python自动提取项目中导入的库及其版本信息

    Python自动提取项目中导入的库及其版本信息

    在我们有时需要迁移或部署项目时,需要知道项目所依赖的三方包和版本,本文就来介绍一下Python自动提取项目中导入的库及其版本信息,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • 有关wxpython pyqt内存占用问题分析

    有关wxpython pyqt内存占用问题分析

    一直觉得wxpython占用内存比较多,在工作中写的一些小程序应用,一对比其它的小程序,发现内存相差确实有点大
    2014-06-06
  • Python之is与==的区别详解

    Python之is与==的区别详解

    这篇文章主要介绍了Python之is与==的区别详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09
  • keras中的backend.clip用法

    keras中的backend.clip用法

    这篇文章主要介绍了keras中的backend.clip用法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-05-05
  • 基于python实现地址和经纬度转换

    基于python实现地址和经纬度转换

    这篇文章主要介绍了基于python实现地址和经纬度转换,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05

最新评论