Django之Apps源码学习
先了解下官方文档的介绍
Django包含了一个已经安装应用的注册表,这个注册表存储着配置信息以及用来自省,同时也维护着可用模型的列表。
这个注册表就是apps,位于django.apps下,本质上是一个django.apps.registry模块下的一个Apps类的实例。
源码面前见真相:
class Apps(object):
这是一个注册表,存储着已安装应用的配置信息,同时也跟踪着模型,例如提供reverse-relations。
初始化的主要属性:
apps_configs:这是一个有顺序的字典,将AppConfig实例的label标签映射到已经安装的entry(AppConfig)上。
主要方法:
populate(installded_app):载入应用的配置信息和模型,这个方法导入每个应用模块然后是每个模型模块,它是线程安全并且是幂等(任意多次执行所产生的影响均与一次执行的影响相同)的,但是不能重入(reentrant),简单百度下,应该是不能进行递归调用的意思。
if self.ready: #该注册表是否已经被填充 return # populate() might be called by two threads in parallel on servers # that create threads before initializing the WSGI callable.
# populate()在初始化WSGI调用之前,可能会被会创建线程的服务器上的两个并行的线程调用。 with self._lock:
#_lock()为Theading.Lock()对象,在with上下文管理器中自动获取锁,处理过后,自动释放锁。 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.
# app_config应该是处于原始的状态,否则下面的代码将不能保证这个顺序匹配INSTALLED_APPS中的顺序。
if self.app_configs: raise RuntimeError("populate() isn't reentrant") # Phase 1: initialize app configs and import app modules. for entry in installed_apps:
# 迭代已安装apps的每一项 if isinstance(entry, AppConfig): app_config = entry else:
# 若INSTALLED_APPS中配置的不是AppConfig类的Python路径而是App模块路径,将会以工厂方式进行创建。 app_config = AppConfig.create(entry) if app_config.label in self.app_configs:
# 检测app_config的唯一性。 raise ImproperlyConfigured( "Application labels aren't unique, " "duplicates: %s" % app_config.label) self.app_configs[app_config.label] = app_config # app_config.label属性默认是由app_name获取的。 app_config.apps = self #将注册表赋给AppConfig类的apps属性。 # 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() self.clear_cache() self.models_ready = True # Phase 3: run ready() methods of app configs.
# 运行apps configs的ready()方法。
for app_config in self.get_app_configs(): app_config.ready() self.ready = True