Django app的加载过程
上一篇介绍到了 Settings
的懒加载机制,配置懒加载也就完成了,程序就回到 execute 函数,接下去就是运行 django.setup()
函数了。
django.setup() 启动程序#
这个代码在 django/__init__.py
中:
def setup(set_prefix=True):
from django.apps import apps
from django.conf import settings
from django.utils.log import configure_logging
configure_logging(settings.LOGGING_CONFIG, settings.LOGGING)
apps.populate(settings.INSTALLED_APPS)
configure_logging
配置日志信息,跳过。加载 settings.INSTALLED_APPS
中的自定义模块以及 models
模块,并保存在 django.apps
中,这是一个全局的 Apps 类实例。这是一个已经安装应用的注册表,这个注册表存储着配置信息以及用来自省,同时也维护这模型的列表。这个类在 django.apps.registry
中定义:
apps = Apps(installed_apps=None)
其中,populate(self, installed_apps=None)
是它的主要方法,这个方法导入每个应用模块,再导入每个模型。这个函数是线程安全的。
def populate(self, installed_apps=None):
if self.ready: #该注册表是否已经被填充
return
with self._lock:
if self.ready:
return
# app_config应该是处于原始的状态,否则下面的代码将不能保证这个顺序匹配INSTALLED_APPS中的顺序。
if self.app_configs:
raise RuntimeError("populate() isn't reentrant")
# Load app configs and app modules.
for entry in installed_apps:# 迭代已安装apps的每一项
if isinstance(entry, AppConfig):
app_config = entry
else:
# 实例化每个app的配置管理对象
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)
self.app_configs[app_config.label] = app_config
# 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:# 检测app_config的唯一性,不允许模块名重复
raise ImproperlyConfigured(
"Application names aren't unique, "
"duplicates: %s" % ", ".join(duplicates))
self.apps_ready = True # 应用 apps 加载完毕
# 导入模型模块
for app_config in self.app_configs.values():
all_models = self.all_models[app_config.label]
app_config.import_models(all_models)
self.clear_cache()
self.models_ready = True
# 运行apps configs的ready()方法
for app_config in self.get_app_configs():
app_config.ready()
self.ready = True
在 for
循环中,使用 AppConfig.create(entry)
加载 settings.INSTALLED_APPS
里面的各模块,并保存在 self.app_configs
中。实例化每个app的配置管理对象有什么好处呢?注意,create
方法是 classmethod
的,这是一个工厂模式,它根据参数来构造出 AppConfig(app_name, app_module)
这样的实例。其中 app_name 表示 INSTALLED_APPS 中指定的应用字符串,app_module 表示根据 app_name 加载到的module。
在 AppConfig
实例的初始化方法中,会记录这些应用的标签
、文件路径
等信息,最终将这些实例会保存在其属性 app_configs
中。接着每个 AppConfig
实例会加载其指定模块的 models
,all_models
定义为 all_models = defaultdict(OrderedDict)
。
模型的加载#
模型的加载在 populate
函数里体现为:
# Load models.
for app_config in self.app_configs.values():
all_models = self.all_models[app_config.label]
app_config.import_models(all_models)
具体的加载函数在 AppConfig
的 import_models
中:
MODELS_MODULE_NAME = 'models'
def import_models(self, all_models):
self.models = all_models # 因此它会再次更新self.all_models,然后all_models会跟着发生变化,然后这里的self.models也会跟着发生变化。
if module_has_submodule(self.module, MODELS_MODULE_NAME):
models_module_name = '%s.%s' % (self.name, MODELS_MODULE_NAME)
self.models_module = import_module(models_module_name)
在module指定的目录或者 package
中,查找是否有定义 models
模块,并将其 import
进来, 最终呈现出来的是:
OrderedDict([
('permission', <class 'django.contrib.auth.models.Permission'>),
('group_permissions', <class 'django.contrib.auth.models.Group_permissions'>),
('group', <class 'django.contrib.auth.models.Group'>),
('user_groups', <class 'django.contrib.auth.models.User_groups'>),
('user_user_permissions', <class 'django.contrib.auth.models.User_user_permissions'>),
('user', <class 'django.contrib.auth.models.User'>)
])
通过呈现结果的对象来看,self.models
已经装载了这些 已经加载好
的模型对象。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架