Django源代码-启动、接收、应用中间件链、路由匹配、完成请求
if __name__=="__main__": # 设置环境变量 export DJANGO_SETTINGS_MODULE="HelloWorld.settings" os.environ.setdefault("DJANGO_SETTINGS_MODULE", "DebugApp.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) { utility=ManagementUtility(argv) { self.argv=argv or sys.argv[:] selfg_name=os.path.basename(self.argv[0]) self.settings_exception=None } utility.execute() { try: subcommand=self.argv[1] except IndexError: subcommand='help' # Display help if no arguments were given. # Preprocess options to extract --settings and --pythonpath. # These options could affect the commands that are available, so they # must be processed early. parser=CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False) parser.add_argument('--settings') parser.add_argument('--pythonpath') parser.add_argument('args', nargs='*') # catch-all try: options, args=parser.parse_known_args(self.argv[2:]) handle_default_options(options) except CommandError: pass # Ignore any option errors at this point. try: # 安装的 app 列表 settings.INSTALLED_APPS except ImproperlyConfigured as exc: self.settings_exception=exc if settings.configured: # Start the auto-reloading dev server even if the code is broken. # The hardcoded condition is a code smell but we can't rely on a # flag on the command class because we haven't located it yet. if subcommand=='runserver' and '--noreload' not in self.argv: try: # 包装 django.setup 并执行 autoreload.check_errors(django.setup)() except Exception: # The exception will be raised later in the child process # started by the autoreloader. Pretend it didn't happen by # loading an empty list of applications. apps.all_models=defaultdict(OrderedDict) apps.app_configs=OrderedDict() apps.apps_ready=apps.models_ready=apps.ready=True # Remove options not compatible with the built-in runserver # (e.g. options for the contrib.staticfiles' runserver). # Changes here require manually testing as described in # #27522. _parser=self.fetch_command('runserver').create_parser('django', 'runserver') _options, _args=_parser.parse_known_args(self.argv[2:]) for _arg in _args: self.argv.remove(_arg) # In all other cases, django.setup() is required to succeed. else: django.setup() { # 安装应用 from django.apps import apps from django.conf import settings from django.urls import set_script_prefix from django.utils.encoding import force_text from django.utils.log import configure_logging # 配置日志 configure_logging(settings.LOGGING_CONFIG, settings.LOGGING) { if logging_config: # First find the logging configuration function ... logging_config_func=import_string(logging_config) logging.config.dictConfig(DEFAULT_LOGGING) # ... then invoke it with the logging settings if logging_settings: logging_config_func(logging_settings) } # 设置脚本前缀 if set_prefix: set_script_prefix( '/' if settings.FORCE_SCRIPT_NAME is None else force_text(settings.FORCE_SCRIPT_NAME) ) { if not prefix.endswith('/'): prefix +='/' _prefixes.value=prefix } # 填充被安装的游戏账号转让平台应用 -------------------- settings.INSTALLED_APPS ------------- 1 !!! apps.populate(settings.INSTALLED_APPS) { # installed_apps===settings.INSTALLED_APPS if self.ready: return # populate() might be called by two threads in parallel on servers # that create threads before initializing the WSGI callable. with self._lock: if self.ready: return # app_config should be pristine, otherwise the code below won't # guarantee that the order matches the order in INSTALLED_APPS. if self.app_configs: raise RuntimeError("populate() isn't reentrant") # 阶段 1: 初始化 app 配置 和 导入 app 模块 # Phase 1: initialize app configs and import app modules. for entry in installed_apps: # 被安装的应用,如:entry===django.contrib.sessions if isinstance(entry, AppConfig): app_config=entry else: # 创建 app_config 对象 app_config=AppConfig.create(entry) { try: # 导入模块,如:django.contrib.sessions # 文件:/Library/Python/2.7/site-packages/django/contrib/sessions/__init__.py ------module------- 1.1 # If import_module succeeds, entry is a path to an app module, # which may specify an app config class with default_app_config. # Otherwise, entry is a path to an app config class or an error. module=import_module(entry) except ImportError: # Track that importing as an app module failed. If importing as an # app config class fails too, we'll trigger the ImportError again. module=None mod_path, _, cls_name=entry.rpartition('.') # Raise the original exception when entry cannot be a path to an # app config class. if not mod_path: raise else: try: # 模块默认app配置 # 文件 /Library/Python/2.7/site-packages/django/contrib/sessions/__init__.py 中 default_app_config ------------- 1.3 # 如:default_app_config='django.contrib.sessions.apps.SessionsConfig' # If this works, the app module specifies an app config class. entry=module.default_app_config except AttributeError: # Otherwise, it simply uses the default app config class. return cls(entry, module) else: # 模块路径,类名 # 如:entry===django.contrib.sessions.apps.SessionsConfig ------------- 1.5 mod_path, _, cls_name=entry.rpartition('.') # 导入默认的app模块 # mod_path===django.contrib.sessions.apps # cls_name===SessionsConfig # If we're reaching this point, we must attempt to load the app config # class located at