搜索
简帛阁>技术文章>Django加载配置的过程详解

Django加载配置的过程详解

一. 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服务启动managepy二引入配置加载配置Django服务启动managepyosenvironsetdefault(DJANGO_SETTINGS_MODULE,uisett
安装源pipinstalldjango22pipinstallmysqlclient146使用pyharm创建django项目django基本配置在settingspy中设置数据库链接DATABASE
刚开始使用django,在创建第一个app时被提示不知道命令runserver,百度得出是环境变量问题。1、配置python变量环境,C:\Python27\;C:\Python27\Scripts
django在引入第三方模块时候保证服务高可用,要设立一个备份接口,当主接口宕机时可以设置一个超市参数来使用备份接口。nginx反向代理器,网站服务器,负载均衡基本命令sudonginx启动s
静态文件配置概述:静态文件交由Web服务器处理,Django本身不处理静态文件。简单处理逻辑如下(以nginx为例):URI请求>按照Web服务器里面配置规则先处理,以nginx为例,主要求
1、settingsINSTALLED_APPS下添加:djangocontribstaticfiles2、settingspy下添加:STATIC_URL'/static/'3、(1)在APP下新建
1、首先在APP目录下创建一个static文件夹如图:ApplicationdefinitionINSTALLED_APPS['djangocontribadmin','djangocontribau
如果是ajax提交,可以按照下面方式处理<scriptsrc="/static/jq/jquery331js"></script><scriptsrc="/stati
1搭建项目配置环境和创建表创建一个ttsx项目djangoadminstartprojectttsx在ttsx下__init__中导入mysqlimportpymysqlpymysqlinsta
有些项目可能涉及到使用多个数据库情况,方法很简单。1在settings中设定DATABASE比如要使用两个数据库:DATABASES{'default':{'NAME':'app_data','E