Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[soc2010/app-loading] implement APP_CLASSES setting

  • Loading branch information...
commit 11a32d6011358414a3f9179319601583e4fc6b32 1 parent 574424f
@arthurk arthurk authored
View
3  django/conf/global_settings.py
@@ -170,6 +170,9 @@
EMAIL_HOST_PASSWORD = ''
EMAIL_USE_TLS = False
+# List of strings representing installed app classes.
+APP_CLASSES = ()
+
# List of strings representing installed apps.
INSTALLED_APPS = ()
View
39 django/core/apps.py
@@ -33,7 +33,7 @@ def __str__(self):
return self.name
def __repr__(self):
- return '<App: %s>' % self.name
+ return '<%s: %s>' % (self.__class__.__name__, self.name)
class AppCache(object):
"""
@@ -78,10 +78,19 @@ def _populate(self):
try:
if self.loaded:
return
+ for app_name in settings.APP_CLASSES:
+ if app_name in self.handled:
+ continue
+ app_module, app_classname = app_name.rsplit('.', 1)
+ app_module = import_module(app_module)
+ app_class = getattr(app_module, app_classname)
+ app_name = app_name.rsplit('.', 2)[0]
+ self.load_app(app_name, True, app_class)
for app_name in settings.INSTALLED_APPS:
if app_name in self.handled:
continue
self.load_app(app_name, True)
+
if not self.nesting_level:
for app_name in self.postponed:
self.load_app(app_name)
@@ -111,7 +120,7 @@ def _populate(self):
finally:
self.write_lock.release()
- def load_app(self, app_name, can_postpone=False):
+ def load_app(self, app_name, can_postpone=False, app_class=App):
"""
Loads the app with the provided fully qualified name, and returns the
model module.
@@ -119,20 +128,7 @@ def load_app(self, app_name, can_postpone=False):
self.handled[app_name] = None
self.nesting_level += 1
- try:
- app_module = import_module(app_name)
- except ImportError:
- # If the import fails, we assume it was because an path to a
- # class was passed (e.g. "foo.bar.MyApp")
- # We split the app_name by the rightmost dot to get the path
- # and classname, and then try importing it again
- if not '.' in app_name:
- raise
- app_name, app_classname = app_name.rsplit('.', 1)
- app_module = import_module(app_name)
- app_class = getattr(app_module, app_classname)
- else:
- app_class = App
+ app_module = import_module(app_name)
# check if an app instance with that name already exists
app_instance = self.find_app(app_name)
@@ -144,10 +140,11 @@ def load_app(self, app_name, can_postpone=False):
app_instance_name = app_name
app_instance = app_class(app_instance_name)
app_instance.module = app_module
+ app_instance.path = app_name
self.app_instances.append(app_instance)
self.installed_apps.append(app_name)
- # check if the app instance specifies a path to models
+ # Check if the app instance specifies a path to models
# if not, we use the models.py file from the package dir
try:
models_path = app_instance.models_path
@@ -179,7 +176,7 @@ def load_app(self, app_name, can_postpone=False):
self.nesting_level -= 1
app_instance.models_module = models
return models
-
+
def find_app(self, name):
"Returns the App instance that matches name"
if '.' in name:
@@ -211,9 +208,9 @@ def get_app(self, app_label, emptyOK=False):
self._populate()
self.write_lock.acquire()
try:
- for app_name in self.installed_apps:
- if app_label == app_name.split('.')[-1]:
- mod = self.load_app(app_name, False)
+ for app in self.app_instances:
+ if app_label == app.name:
+ mod = self.load_app(app.path, False)
if mod is None:
if emptyOK:
return None
View
8 django/db/models/options.py
@@ -99,7 +99,13 @@ def contribute_to_class(self, cls, name):
# If the db_table wasn't provided, use the db_prefix + module_name.
if not self.db_table:
app_instance = cache.find_app(self.app_label)
- self.db_table = "%s_%s" % (app_instance.db_prefix, self.module_name)
+ if not app_instance:
+ # use the app label when no app instance was found, this
+ # can happen when the app cache is not initialized but the
+ # model is imported
+ self.db_table = "%s_%s" % (self.app_label, self.module_name)
+ else:
+ self.db_table = "%s_%s" % (app_instance.db_prefix, self.module_name)
self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
def _prepare(self, model):
View
21 tests/appcachetests/runtests.py
@@ -18,10 +18,13 @@ class AppCacheTestCase(unittest.TestCase):
def setUp(self):
self.old_installed_apps = settings.INSTALLED_APPS
+ self.old_app_classes = settings.APP_CLASSES
+ settings.APP_CLASSES = ()
settings.INSTALLED_APPS = ()
def tearDown(self):
settings.INSTALLED_APPS = self.old_installed_apps
+ settings.APP_CLASSES = self.old_app_classes
# The appcache imports models modules. We need to delete the
# imported module from sys.modules after the test has run.
@@ -102,7 +105,7 @@ def test_db_prefix_exception(self):
Test that an exception is raised if two app instances
have the same db_prefix attribute
"""
- settings.INSTALLED_APPS = ('nomodel_app.MyApp', 'model_app.MyOtherApp',)
+ settings.APP_CLASSES = ('nomodel_app.MyApp', 'model_app.MyOtherApp',)
self.assertRaises(ImproperlyConfigured, cache.get_apps)
class GetAppTests(AppCacheTestCase):
@@ -264,10 +267,10 @@ def test_without_models(self):
def test_custom_app(self):
"""
Test that a custom app instance is created if the function
- gets passed a classname
+ gets passed a custom app class
"""
from nomodel_app import MyApp
- rv = cache.load_app('nomodel_app.MyApp')
+ rv = cache.load_app('nomodel_app', False, MyApp)
app = cache.app_instances[0]
self.assertEqual(len(cache.app_instances), 1)
self.assertEqual(app.name, 'nomodel_app')
@@ -278,10 +281,11 @@ def test_custom_models_path(self):
"""
Test that custom models are imported correctly
"""
- rv = cache.load_app('model_app.MyApp')
+ from nomodel_app import MyApp
+ rv = cache.load_app('model_app', False, MyApp)
app = cache.app_instances[0]
- self.assertEqual(app.models_module.__name__, 'model_app.othermodels')
- self.assertEqual(rv.__name__, 'model_app.othermodels')
+ self.assertEqual(app.models_module.__name__, 'model_app.models')
+ self.assertEqual(rv.__name__, 'model_app.models')
def test_twice(self):
"""
@@ -304,10 +308,11 @@ def test_installed_apps(self):
"""
Test that the installed_apps attribute is populated correctly
"""
- settings.INSTALLED_APPS = ('model_app', 'nomodel_app.MyApp',)
+ settings.APP_CLASSES = ('nomodel_app.MyApp',)
+ settings.INSTALLED_APPS = ('model_app',)
# populate cache
cache.get_app_errors()
- self.assertEqual(cache.installed_apps, ['model_app', 'nomodel_app',])
+ self.assertEqual(cache.installed_apps, ['nomodel_app', 'model_app',])
class RegisterModelsTests(AppCacheTestCase):
"""Tests for the register_models function"""
Please sign in to comment.
Something went wrong with that request. Please try again.