diff --git a/django/contrib/admin/views/doc.py b/django/contrib/admin/views/doc.py index 7750a5d6cb..acc478d31b 100644 --- a/django/contrib/admin/views/doc.py +++ b/django/contrib/admin/views/doc.py @@ -151,7 +151,7 @@ def model_detail(request, app_label, model_name): except ImproperlyConfigured: raise Http404, "App %r not found" % app_label model = None - for m in app_mod._MODELS: + for m in models.get_models(app_mod): if m._meta.object_name.lower() == model_name: model = m break diff --git a/django/core/management.py b/django/core/management.py index 53f3ce7bc1..7b498b2546 100644 --- a/django/core/management.py +++ b/django/core/management.py @@ -438,7 +438,7 @@ def get_admin_index(app): app_label = app_models[0]._meta.app_label output.append('{%% if perms.%s %%}' % app_label) output.append('<div class="module"><h2>%s</h2><table>' % app_label.title()) - for klass in mod._MODELS: + for klass in app_models: if klass._meta.admin: output.append(MODULE_TEMPLATE % { 'app': app_label, diff --git a/django/db/models/base.py b/django/db/models/base.py index b3a4ab361f..626591c0e2 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -7,6 +7,7 @@ from django.db.models.query import orderlist2sql from django.db.models.options import Options, AdminOptions from django.db import connection, backend from django.db.models import signals +from django.db.models.loading import register_models from django.dispatch import dispatcher from django.core.exceptions import ObjectDoesNotExist from django.utils.functional import curry @@ -46,8 +47,7 @@ class ModelBase(type): new_class._prepare() - # Populate the _MODELS member on the module the class is in. - model_module.__dict__.setdefault('_MODELS', []).append(new_class) + register_models(new_class._meta.app_label, new_class) return new_class def cmp_cls(x, y): diff --git a/django/db/models/loading.py b/django/db/models/loading.py index 2464a632a6..a64c3ee0fb 100644 --- a/django/db/models/loading.py +++ b/django/db/models/loading.py @@ -6,6 +6,7 @@ from django.core.exceptions import ImproperlyConfigured __all__ = ('get_apps', 'get_app', 'get_models', 'get_model', 'register_models') _app_list = None # Cache of installed apps. +_app_models = {} # Dictionary of models against app module name def get_apps(): "Returns a list of all installed modules that contain models." @@ -33,11 +34,11 @@ def get_models(app_mod=None): returns a list of all installed models. """ if app_mod: - return getattr(app_mod, '_MODELS', ()) + return _app_models.get(app_mod.__name__.split('.')[-2], ()) else: model_list = [] for app_mod in get_apps(): - model_list.extend(getattr(app_mod, '_MODELS', ())) + model_list.extend(get_models(app_mod)) return model_list def get_model(app_label, model_name): @@ -51,13 +52,8 @@ def get_model(app_label, model_name): model._meta.app_label == app_label: return model -def register_models(app_mod, *models): +def register_models(app_label, *models): """ - Use this from an app's models.py module to register imported Model classes - as belonging to the app. e.g.: - - register_models(sys.modules[__name__], Article, Reporter) + Register a set of models as belonging to an app. """ - if not hasattr(app_mod, '_MODELS'): - app_mod._MODELS = [] - app_mod._MODELS.extend(models) + _app_models.setdefault(app_label, []).extend(models) diff --git a/django/db/models/options.py b/django/db/models/options.py index c9ccd293f7..c06ecabc1b 100644 --- a/django/db/models/options.py +++ b/django/db/models/options.py @@ -167,7 +167,7 @@ class Options: if not hasattr(self, '_ordered_objects'): objects = [] # TODO - #for klass in get_app(self.app_label)._MODELS: + #for klass in get_models(get_app(self.app_label)): # opts = klass._meta # if opts.order_with_respect_to and opts.order_with_respect_to.rel \ # and self == opts.order_with_respect_to.rel.to._meta: diff --git a/tests/runtests.py b/tests/runtests.py index c484b9ecc5..c716811123 100755 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import os, re, sys, time, traceback +import django.db.models # doctest is included in the same package as this module, because this testing # framework uses features only available in the Python 2.4 version of doctest, @@ -142,7 +143,8 @@ class TestRunner: # Run the API tests. p = doctest.DocTestParser() - test_namespace = dict([(m._meta.object_name, m) for m in mod._MODELS]) + test_namespace = dict([(m._meta.object_name, m) \ + for m in django.db.models.get_models(mod)]) dtest = p.get_doctest(mod.API_TESTS, test_namespace, model_name, None, None) # Manually set verbose=False, because "-v" command-line parameter # has side effects on doctest TestRunner class.