Django源码分析(五):应用及模型加载

起步

上节咱们了解到,django 是如何进行处理请求的。python

那么 django 是如何进行 app 模块导入的。django

咱们所知道的。缓存

运行 django 应用分为 生产 和 本地开发 模式。一个经过 wsgi.py 来达到生产环境的运行,另外一个经过 manage.py runserver 来达到本地开发的运行。安全

可是咱们发现,这俩处入口均有 django.setup() 这一步。服务器

这俩点均有一些不一样之处,可是总体功能类似。app

开始

咱们从 setup 这个功能函数提及。函数

def setup(set_prefix=True):
    """配置 logging 及应用注册。 """
    # 这里的 apps 是一个单例模式,指向 django/apps/registry 下的 Apps 这个类
    from django.apps import apps
    from django.conf import settings
    from django.urls import set_script_prefix
    from django.utils.log import configure_logging

    # 从 settings 文件下读取 LOGGING_CONFIG 配置日志文件
    configure_logging(settings.LOGGING_CONFIG, settings.LOGGING)
    # 这里只针对开发模式下有效,生产环境忽略
    if set_prefix:
        set_script_prefix(
            '/' if settings.FORCE_SCRIPT_NAME is None else settings.FORCE_SCRIPT_NAME
        )
    # 重点其实在这里,从 settings 文件获取 INSTALLED_APPS 配置
    apps.populate(settings.INSTALLED_APPS)

复制代码

接下来,咱们移步到 populate 下的函数。url

def populate(self, installed_apps=None):
    """加载应用配置和模型 导入每一个应用程序模块,而后导入每一个模型模块。 它是线程安全的、幂等的,但不是可重入的。 """
    if self.ready:
        return

    # 在初始化 WSGI 回调以前,在服务器上建立的线程可能会并行调用 `populate`
    # 此处设置了线程锁
    with self._lock:
        if self.ready:
            return

        # RLock 防止其余线程进入这个部分。下面的比较和设置操做是原子性的。
        if self.loading:
            # Prevent reentrant calls to avoid running AppConfig.ready()
            # methods twice.
            raise RuntimeError("populate() isn't reentrant")
        self.loading = True

        # 阶段 1: 初始化 app 配置和导入 app 模型
        for entry in installed_apps:
            if isinstance(entry, AppConfig):
                app_config = entry
            else:
                # 这里经过一个工厂方法创造出一个应用实例
                app_config = AppConfig.create(entry)
            if app_config.label in self.app_configs:
                raise ImproperlyConfigured(
                    "Application labels aren't unique, "
                    "duplicates: %s" % app_config.label)

            # 载入到 app_configs 配置
            # key 为 应用标签,值为 app 实例
            self.app_configs[app_config.label] = app_config
            app_config.apps = self

        # 检测重复的 app 名称,确保惟一性
        counts = Counter(
            app_config.name for app_config in self.app_configs.values())
        duplicates = [
            name for name, count in counts.most_common() if count > 1]
        if duplicates:
            raise ImproperlyConfigured(
                "Application names aren't unique, "
                "duplicates: %s" % ", ".join(duplicates))

        # 设置应用加载完成标识位
        self.apps_ready = True

        # 阶段 2: 导入模型模块
        for app_config in self.app_configs.values():
            app_config.import_models()

        # 清空缓存
        self.clear_cache()

        # 设置模型加载完成标识位
        self.models_ready = True

        # 阶段 3: 运行 app 下的 ready 方法(钩子方法)
        for app_config in self.get_app_configs():
            app_config.ready()

        # 初始化完成
        self.ready = True

复制代码

总结

到此,咱们在 run 一个 django 应用的时候,会调用 djangosetup 方法,主要是载入全部的应用和模型。spa

相关文章
相关标签/搜索