diff --git a/django/core/apps/cache.py b/django/core/apps/cache.py index 697cf9e516..92b9f8d8d4 100644 --- a/django/core/apps/cache.py +++ b/django/core/apps/cache.py @@ -320,14 +320,27 @@ class AppCache(object): return self.all_models[app_label].get(model_name.lower()) def set_available_apps(self, available): + """ + Restricts the set of installed apps used by get_app_config[s]. + + available must be an iterable of application names. + + Primarily used for performance optimization in TransactionTestCase. + """ + if self.available_apps is not None: + raise RuntimeError("set_available_apps() may be called only once " + "in a row; make sure it's paired with unset_available_apps()") available = set(available) - installed = set(settings.INSTALLED_APPS) + installed = set(app_config.name for app_config in self.get_app_configs()) if not available.issubset(installed): raise ValueError("Available apps isn't a subset of installed " "apps, extra apps: %s" % ", ".join(available - installed)) self.available_apps = available def unset_available_apps(self): + """ + Cancels a previous call to set_available_apps(). + """ self.available_apps = None ### DANGEROUS METHODS ### (only used to preserve existing tests) @@ -340,11 +353,15 @@ class AppCache(object): else: app_config.import_models(self.all_models[app_config.label]) self.app_configs[app_config.label] = app_config + if self.available_apps is not None: + self.available_apps.add(app_config.name) return app_config def _end_with_app(self, app_config): if app_config is not None: del self.app_configs[app_config.label] + if self.available_apps is not None: + self.available_apps.discard(app_config.name) @contextmanager def _with_app(self, app_name): diff --git a/tests/proxy_model_inheritance/tests.py b/tests/proxy_model_inheritance/tests.py index 91fcbbcc09..5f33ec2fee 100644 --- a/tests/proxy_model_inheritance/tests.py +++ b/tests/proxy_model_inheritance/tests.py @@ -6,22 +6,19 @@ import sys from django.core.apps import app_cache from django.core.management import call_command from django.test import TestCase, TransactionTestCase -from django.test.utils import override_settings from django.utils._os import upath from .models import (ConcreteModel, ConcreteModelSubclass, ConcreteModelSubclassProxy) -# Required for available_apps. -@override_settings(INSTALLED_APPS=['app1', 'app2']) class ProxyModelInheritanceTests(TransactionTestCase): """ Proxy model inheritance across apps can result in migrate not creating the table for the proxied model (as described in #12286). This test creates two dummy apps and calls migrate, then verifies that the table has been created. """ - available_apps = ['app1', 'app2'] + available_apps = [] def setUp(self): self.old_sys_path = sys.path[:]