Merged Apps.populate_apps() and populate_models().
After the recent series of refactorings, there's no reason to keep two distinct methods. Refs #21681.
This commit is contained in:
parent
966de84973
commit
1c242a297b
|
@ -13,5 +13,4 @@ def setup():
|
||||||
# INSTALLED_APPS or any other setting) and populate the app registry.
|
# INSTALLED_APPS or any other setting) and populate the app registry.
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
apps.populate_apps(settings.INSTALLED_APPS)
|
apps.populate(settings.INSTALLED_APPS)
|
||||||
apps.populate_models()
|
|
||||||
|
|
|
@ -152,8 +152,7 @@ class AppConfig(object):
|
||||||
# Dictionary of models for this app, primarily maintained in the
|
# Dictionary of models for this app, primarily maintained in the
|
||||||
# 'all_models' attribute of the Apps this AppConfig is attached to.
|
# 'all_models' attribute of the Apps this AppConfig is attached to.
|
||||||
# Injected as a parameter because it gets populated when models are
|
# Injected as a parameter because it gets populated when models are
|
||||||
# imported, which might happen before populate_models() runs (or at
|
# imported, which might happen before populate() imports models.
|
||||||
# least used to).
|
|
||||||
self.models = all_models
|
self.models = all_models
|
||||||
|
|
||||||
if module_has_submodule(self.module, MODELS_MODULE_NAME):
|
if module_has_submodule(self.module, MODELS_MODULE_NAME):
|
||||||
|
|
|
@ -41,43 +41,39 @@ class Apps(object):
|
||||||
# set_available_apps and set_installed_apps.
|
# set_available_apps and set_installed_apps.
|
||||||
self.stored_app_configs = []
|
self.stored_app_configs = []
|
||||||
|
|
||||||
# Internal flags used when populating the registry.
|
# Whether the registry is populated.
|
||||||
self._apps_loaded = False
|
self.ready = False
|
||||||
self._models_loaded = False
|
|
||||||
|
|
||||||
# Pending lookups for lazy relations.
|
# Pending lookups for lazy relations.
|
||||||
self._pending_lookups = {}
|
self._pending_lookups = {}
|
||||||
|
|
||||||
# Populate apps and models, unless it's the master registry.
|
# Populate apps and models, unless it's the master registry.
|
||||||
if installed_apps is not None:
|
if installed_apps is not None:
|
||||||
self.populate_apps(installed_apps)
|
self.populate(installed_apps)
|
||||||
self.populate_models()
|
|
||||||
|
|
||||||
def populate_apps(self, installed_apps=None):
|
def populate(self, installed_apps=None):
|
||||||
"""
|
"""
|
||||||
Populate app-related information.
|
Loads application configurations and models.
|
||||||
|
|
||||||
This method imports each application module.
|
This method imports each application module and then each model module.
|
||||||
|
|
||||||
It is thread safe and idempotent, but not reentrant.
|
It is thread safe and idempotent, but not reentrant.
|
||||||
"""
|
"""
|
||||||
if self._apps_loaded:
|
if self.ready:
|
||||||
return
|
return
|
||||||
# Since populate_apps() may be a side effect of imports, and since
|
# Since populate() may be a side effect of imports, and since it will
|
||||||
# it will itself import modules, an ABBA deadlock between threads
|
# itself import modules, an ABBA deadlock between threads would be
|
||||||
# would be possible if we didn't take the import lock. See #18251.
|
# possible if we didn't take the import lock. See #18251.
|
||||||
with import_lock():
|
with import_lock():
|
||||||
if self._apps_loaded:
|
if self.ready:
|
||||||
return
|
return
|
||||||
|
|
||||||
# app_config should be pristine, otherwise the code below won't
|
# app_config should be pristine, otherwise the code below won't
|
||||||
# guarantee that the order matches the order in INSTALLED_APPS.
|
# guarantee that the order matches the order in INSTALLED_APPS.
|
||||||
if self.app_configs:
|
if self.app_configs:
|
||||||
raise RuntimeError("populate_apps() isn't reentrant")
|
raise RuntimeError("populate() isn't reentrant")
|
||||||
|
|
||||||
# Application modules aren't expected to import anything, and
|
# Load app configs and app modules.
|
||||||
# especially not other application modules, even indirectly.
|
|
||||||
# Therefore we simply import them sequentially.
|
|
||||||
for entry in installed_apps:
|
for entry in installed_apps:
|
||||||
if isinstance(entry, AppConfig):
|
if isinstance(entry, AppConfig):
|
||||||
app_config = entry
|
app_config = entry
|
||||||
|
@ -85,36 +81,13 @@ class Apps(object):
|
||||||
app_config = AppConfig.create(entry)
|
app_config = AppConfig.create(entry)
|
||||||
self.app_configs[app_config.label] = app_config
|
self.app_configs[app_config.label] = app_config
|
||||||
|
|
||||||
self.clear_cache()
|
# Load models.
|
||||||
self._apps_loaded = True
|
|
||||||
|
|
||||||
def populate_models(self):
|
|
||||||
"""
|
|
||||||
Populate model-related information.
|
|
||||||
|
|
||||||
This method imports each models module.
|
|
||||||
|
|
||||||
It is thread safe, idempotent and reentrant.
|
|
||||||
"""
|
|
||||||
if self._models_loaded:
|
|
||||||
return
|
|
||||||
# Since populate_models() may be a side effect of imports, and since
|
|
||||||
# it will itself import modules, an ABBA deadlock between threads
|
|
||||||
# would be possible if we didn't take the import lock. See #18251.
|
|
||||||
with import_lock():
|
|
||||||
if self._models_loaded:
|
|
||||||
return
|
|
||||||
|
|
||||||
if not self._apps_loaded:
|
|
||||||
raise RuntimeError(
|
|
||||||
"populate_models() must run after populate_apps()")
|
|
||||||
|
|
||||||
for app_config in self.app_configs.values():
|
for app_config in self.app_configs.values():
|
||||||
all_models = self.all_models[app_config.label]
|
all_models = self.all_models[app_config.label]
|
||||||
app_config.import_models(all_models)
|
app_config.import_models(all_models)
|
||||||
|
|
||||||
self.clear_cache()
|
self.clear_cache()
|
||||||
self._models_loaded = True
|
self.ready = True
|
||||||
|
|
||||||
for app_config in self.get_app_configs():
|
for app_config in self.get_app_configs():
|
||||||
app_config.setup()
|
app_config.setup()
|
||||||
|
@ -123,21 +96,11 @@ class Apps(object):
|
||||||
"""
|
"""
|
||||||
Raises an exception if the registry isn't ready.
|
Raises an exception if the registry isn't ready.
|
||||||
"""
|
"""
|
||||||
if not self._models_loaded:
|
if not self.ready:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"App registry isn't populated yet. "
|
"App registry isn't populated yet. "
|
||||||
"Have you called django.setup()?")
|
"Have you called django.setup()?")
|
||||||
|
|
||||||
@property
|
|
||||||
def ready(self):
|
|
||||||
"""
|
|
||||||
Whether the registry is fully populated.
|
|
||||||
|
|
||||||
Useful for code that wants to cache the results of get_models() for
|
|
||||||
themselves once it is safe to do so.
|
|
||||||
"""
|
|
||||||
return self._models_loaded # implies self._apps_loaded.
|
|
||||||
|
|
||||||
def get_app_configs(self, only_with_models_module=False):
|
def get_app_configs(self, only_with_models_module=False):
|
||||||
"""
|
"""
|
||||||
Imports applications and returns an iterable of app configs.
|
Imports applications and returns an iterable of app configs.
|
||||||
|
@ -306,19 +269,16 @@ class Apps(object):
|
||||||
self.check_ready()
|
self.check_ready()
|
||||||
self.stored_app_configs.append(self.app_configs)
|
self.stored_app_configs.append(self.app_configs)
|
||||||
self.app_configs = OrderedDict()
|
self.app_configs = OrderedDict()
|
||||||
|
self.ready = False
|
||||||
self.clear_cache()
|
self.clear_cache()
|
||||||
self._apps_loaded = False
|
self.populate(installed)
|
||||||
self.populate_apps(installed)
|
|
||||||
self._models_loaded = False
|
|
||||||
self.populate_models()
|
|
||||||
|
|
||||||
def unset_installed_apps(self):
|
def unset_installed_apps(self):
|
||||||
"""
|
"""
|
||||||
Cancels a previous call to set_installed_apps().
|
Cancels a previous call to set_installed_apps().
|
||||||
"""
|
"""
|
||||||
self.app_configs = self.stored_app_configs.pop()
|
self.app_configs = self.stored_app_configs.pop()
|
||||||
self._apps_loaded = True
|
self.ready = True
|
||||||
self._models_loaded = True
|
|
||||||
self.clear_cache()
|
self.clear_cache()
|
||||||
|
|
||||||
def clear_cache(self):
|
def clear_cache(self):
|
||||||
|
|
|
@ -121,8 +121,7 @@ def get_commands():
|
||||||
# avoid catching ImproperlyConfigured errors that aren't caused
|
# avoid catching ImproperlyConfigured errors that aren't caused
|
||||||
# by the absence of a settings module.
|
# by the absence of a settings module.
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
apps.populate_apps(installed_apps)
|
apps.populate(installed_apps)
|
||||||
apps.populate_models()
|
|
||||||
app_configs = apps.get_app_configs()
|
app_configs = apps.get_app_configs()
|
||||||
app_names = [app_config.name for app_config in app_configs]
|
app_names = [app_config.name for app_config in app_configs]
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue