1. 程式人生 > 其它 >Django app應用的配置載入過程

Django app應用的配置載入過程

wsgi.py

import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "apc.settings")
application = get_wsgi_application()   #獲取application

django.core.wsgi.py

import django
from django.core.handlers.wsgi import WSGIHandler


def get_wsgi_application():
    """
    The public interface to Django's WSGI support. Return a WSGI callable.

    Avoids making django.core.handlers.WSGIHandler a public API, in case the
    internal WSGI implementation changes or moves in the future.
    """
    django.setup(set_prefix=False)     # Django 初始化,點進去檢視
    return WSGIHandler()

django.init.py

def setup(set_prefix=True):
    """
    Configure the settings (this happens as a side effect of accessing the
    first setting), configure logging and populate the app registry.
    Set the thread-local urlresolvers script prefix if `set_prefix` is True.
    """
    from django.apps import apps
    from django.conf import settings
    from django.urls import set_script_prefix
    from django.utils.log import configure_logging

    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
        )
    apps.populate(settings.INSTALLED_APPS)     # 從配置中讀取註冊的app,然後填充每個app對應的配置

django.app.registry.Apps

def populate(self, installed_apps=None):
       if self.ready:     # 保證應用配置只填充一次
           return
       with self._lock:
           if self.ready:
               return

           if self.loading:
               # Prevent reentrant calls to avoid running AppConfig.ready()
               # methods twice.
               raise RuntimeError("populate() isn't reentrant")
           self.loading = True

           # Phase 1: initialize app configs and import app modules.
           for entry in installed_apps:
               if isinstance(entry, AppConfig):    # 註冊的時候指定的是AppConfig
                   app_config = entry
               else:
                   app_config = AppConfig.create(entry)   # 如果註冊app時指定的是app的名稱,則會根據app的default_app_config屬性查詢對應的配置
               if app_config.label in self.app_configs:
                   raise ImproperlyConfigured(
                       "Application labels aren't unique, "
                       "duplicates: %s" % app_config.label)

               self.app_configs[app_config.label] = app_config
               app_config.apps = self

           # Check for duplicate app names.
           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

           # Phase 2: import models modules.
           for app_config in self.app_configs.values():
               app_config.import_models()  # 根據label 確認models

           self.clear_cache()

           self.models_ready = True

           # Phase 3: run ready() methods of app configs.
           for app_config in self.get_app_configs():
               app_config.ready()    # 執行配置中定義的ready 方法

           self.ready = True

因此,配置app 有兩種方式。
一種是直接定義繼承AppConfig 的配置類,將該類註冊在settings中;
一種是在app的settings中註冊最外層的應用名稱,然後給app賦值default_app_config屬性,使用該屬性指向定義的AppConfig 類,這種方式可以多個app共用同一個配置