summaryrefslogtreecommitdiff
path: root/django/apps
diff options
context:
space:
mode:
authorAymeric Augustin <aymeric.augustin@m4x.org>2013-12-30 15:42:15 +0100
committerAymeric Augustin <aymeric.augustin@m4x.org>2013-12-30 22:11:17 +0100
commit80d74097b4bd7186ad99b6d41d0ed90347a39b21 (patch)
tree7b00c5113c311aaaeba4393701151e916ae7f9f0 /django/apps
parent7ed20e015335076fc98ad805eaf241f8a0d872d5 (diff)
Stopped populating the app registry as a side effect.
Since it triggers imports, it shouldn't be done lightly. This commit adds a public API for doing it explicitly, django.setup(), and does it automatically when using manage.py and wsgi.py.
Diffstat (limited to 'django/apps')
-rw-r--r--django/apps/base.py7
-rw-r--r--django/apps/registry.py44
2 files changed, 24 insertions, 27 deletions
diff --git a/django/apps/base.py b/django/apps/base.py
index eaf8993624..ae2abaae84 100644
--- a/django/apps/base.py
+++ b/django/apps/base.py
@@ -114,8 +114,6 @@ class AppConfig(object):
Returns the model with the given case-insensitive model_name.
Raises LookupError if no model exists with this name.
-
- This method assumes that apps.populate_models() has run.
"""
if self.models is None:
raise LookupError(
@@ -140,8 +138,6 @@ class AppConfig(object):
Set the corresponding keyword argument to True to include such models.
Keyword arguments aren't documented; they're a private API.
-
- This method assumes that apps.populate_models() has run.
"""
for model in self.models.values():
if model._deferred and not include_deferred:
@@ -156,7 +152,8 @@ class AppConfig(object):
# Dictionary of models for this app, primarily maintained in the
# 'all_models' attribute of the Apps this AppConfig is attached to.
# Injected as a parameter because it gets populated when models are
- # imported, which may happen before populate_models() runs.
+ # imported, which might happen before populate_models() runs (or at
+ # least used to).
self.models = all_models
if module_has_submodule(self.module, MODELS_MODULE_NAME):
diff --git a/django/apps/registry.py b/django/apps/registry.py
index 35c4ac3cea..0e39068e1f 100644
--- a/django/apps/registry.py
+++ b/django/apps/registry.py
@@ -3,7 +3,6 @@ import os
import sys
import warnings
-from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.utils import lru_cache
from django.utils.module_loading import import_lock
@@ -79,8 +78,6 @@ class Apps(object):
# Application modules aren't expected to import anything, and
# especially not other application modules, even indirectly.
# Therefore we simply import them sequentially.
- if installed_apps is None:
- installed_apps = settings.INSTALLED_APPS
for entry in installed_apps:
if isinstance(entry, AppConfig):
app_config = entry
@@ -108,7 +105,9 @@ class Apps(object):
if self._models_loaded:
return
- self.populate_apps()
+ if not self._apps_loaded:
+ raise RuntimeError(
+ "populate_models() must run after populate_apps()")
# Models modules are likely to import other models modules, for
# example to reference related objects. As a consequence:
@@ -144,6 +143,15 @@ class Apps(object):
for app_config in self.get_app_configs():
app_config.setup()
+ def check_ready(self):
+ """
+ Raises an exception if the registry isn't ready.
+ """
+ if not self._models_loaded:
+ raise RuntimeError(
+ "App registry isn't populated yet. "
+ "Have you called django.setup()?")
+
@property
def ready(self):
"""
@@ -161,11 +169,7 @@ class Apps(object):
If only_with_models_module in True (non-default), imports models and
considers only applications containing a models module.
"""
- if only_with_models_module:
- self.populate_models()
- else:
- self.populate_apps()
-
+ self.check_ready()
for app_config in self.app_configs.values():
if only_with_models_module and app_config.models_module is None:
continue
@@ -180,11 +184,7 @@ class Apps(object):
If only_with_models_module in True (non-default), imports models and
considers only applications containing a models module.
"""
- if only_with_models_module:
- self.populate_models()
- else:
- self.populate_apps()
-
+ self.check_ready()
app_config = self.app_configs.get(app_label)
if app_config is None:
raise LookupError("No installed app with label '%s'." % app_label)
@@ -208,8 +208,7 @@ class Apps(object):
Set the corresponding keyword argument to True to include such models.
"""
- self.populate_models()
-
+ self.check_ready()
if app_mod:
warnings.warn(
"The app_mod argument of get_models is deprecated.",
@@ -236,7 +235,7 @@ class Apps(object):
Raises LookupError if no application exists with this label, or no
model exists with this name in the application.
"""
- self.populate_models()
+ self.check_ready()
return self.get_app_config(app_label).get_model(model_name.lower())
def register_model(self, app_label, model):
@@ -328,7 +327,8 @@ class Apps(object):
imports safely (eg. that could lead to registering listeners twice),
models are registered when they're imported and never removed.
"""
- self.stored_app_configs.append((self.app_configs, self._apps_loaded, self._models_loaded))
+ self.check_ready()
+ self.stored_app_configs.append(self.app_configs)
self.app_configs = OrderedDict()
self.clear_cache()
self._apps_loaded = False
@@ -340,7 +340,9 @@ class Apps(object):
"""
Cancels a previous call to set_installed_apps().
"""
- self.app_configs, self._apps_loaded, self._models_loaded = self.stored_app_configs.pop()
+ self.app_configs = self.stored_app_configs.pop()
+ self._apps_loaded = True
+ self._models_loaded = True
self.clear_cache()
def clear_cache(self):
@@ -429,9 +431,7 @@ class Apps(object):
warnings.warn(
"[a.path for a in get_app_configs()] supersedes get_app_paths().",
PendingDeprecationWarning, stacklevel=2)
-
- self.populate_models()
-
+ self.check_ready()
app_paths = []
for app in self.get_apps():
app_paths.append(self._get_app_path(app))