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.