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

相關文章
相關標籤/搜索