summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAymeric Augustin <aymeric.augustin@m4x.org>2014-01-10 23:06:19 +0100
committerAymeric Augustin <aymeric.augustin@m4x.org>2014-01-10 23:43:10 +0100
commit3326a412ccde9f72e22a070a0b4d922048ed2286 (patch)
tree7583ee99e53ab3d3bf846f1aec79dc34d330d2cf
parent81bb8d12209a419142b1bf6961fbf9fc44419dcd (diff)
Deprecated importing a model before loading its application.
Refs #21719, #21680.
-rw-r--r--django/db/models/base.py10
-rw-r--r--docs/internals/deprecation.txt6
-rw-r--r--docs/ref/applications.txt7
-rw-r--r--docs/releases/1.7.txt15
-rwxr-xr-xtests/runtests.py7
5 files changed, 40 insertions, 5 deletions
diff --git a/django/db/models/base.py b/django/db/models/base.py
index 531dd8adcc..d7b54b9268 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -3,7 +3,7 @@ from __future__ import unicode_literals
import copy
import sys
from functools import update_wrapper
-from django.utils.six.moves import zip
+import warnings
from django.apps import apps
from django.apps.base import MODELS_MODULE_NAME
@@ -25,6 +25,7 @@ from django.utils.translation import ugettext_lazy as _
from django.utils.functional import curry
from django.utils.encoding import force_str, force_text
from django.utils import six
+from django.utils.six.moves import zip
from django.utils.text import get_text_list, capfirst
@@ -103,6 +104,13 @@ class ModelBase(type):
# For 'django.contrib.sites.models', this would be 'sites'.
# For 'geo.models.places' this would be 'geo'.
+ warnings.warn(
+ "Model class %s.%s doesn't declare an explicit app_label "
+ "and either isn't in an application in INSTALLED_APPS "
+ "or else was imported before its application was loaded. "
+ "This will no longer be supported in Django 1.9."
+ % (module, name), PendingDeprecationWarning, stacklevel=2)
+
model_module = sys.modules[new_class.__module__]
package_components = model_module.__name__.split('.')
package_components.reverse() # find the last occurrence of 'models'
diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt
index 1b8b45a520..514561e1ff 100644
--- a/docs/internals/deprecation.txt
+++ b/docs/internals/deprecation.txt
@@ -170,6 +170,12 @@ these changes.
* ``allow_syncdb`` on database routers will no longer automatically become
``allow_migrate``.
+* All models will need to be defined inside an installed application or
+ declare an explicit :attr:`~django.db.models.Options.app_label`.
+ Furthermore, it won't be possible to import them before their application
+ is loaded. In particular, it won't be possible to import models inside
+ the root package of their application.
+
* If models are organized in a package, Django will no longer look for
:ref:`initial SQL data<initial-sql>` in ``myapp/models/sql/``. Move your
custom SQL files to ``myapp/sql/``.
diff --git a/docs/ref/applications.txt b/docs/ref/applications.txt
index a44062808e..e496f24487 100644
--- a/docs/ref/applications.txt
+++ b/docs/ref/applications.txt
@@ -181,6 +181,13 @@ Methods
as registering signals. It is called as soon as the registry is fully
populated.
+ You cannot import models in modules that define application configuration
+ classes, but you can use :meth:`get_model` to access a model class by
+ name, like this::
+
+ def ready(self):
+ MyModel = self.get_model('MyModel')
+
Application registry
====================
diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt
index a8becf1bab..9fcad38931 100644
--- a/docs/releases/1.7.txt
+++ b/docs/releases/1.7.txt
@@ -677,9 +677,18 @@ directory and a subdirectory on :envvar:`PYTHONPATH`. Refer to the section on
the new project layout in the :doc:`1.4 release notes </releases/1.4>` for
migration instructions.
-You should make sure that your project doesn't import models from applications
-that aren't in :setting:`INSTALLED_APPS`. Relations involving such models may
-not be created properly. Future versions of Django may forbid this entirely.
+You should make sure that:
+
+* All models are defined in applications that are listed in
+ :setting:`INSTALLED_APPS` or have an explicit
+ :attr:`~django.db.models.Options.app_label`.
+
+* Models aren't imported as a side-effect of loading their application.
+ Specifically, you shouldn't import models in the root module of an
+ application nor in the module that define its configuration class.
+
+Django will enforce these requirements as of version 1.9, after a deprecation
+period.
Subclassing AppCommand
^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/runtests.py b/tests/runtests.py
index bb14a27fd6..dcd9c885bd 100755
--- a/tests/runtests.py
+++ b/tests/runtests.py
@@ -130,6 +130,11 @@ def setup(verbosity, test_labels):
'django.contrib.comments is deprecated and will be removed before Django 1.8.',
DeprecationWarning
)
+ warnings.filterwarnings(
+ 'ignore',
+ 'Model class django.contrib.comments.models.*supported in Django 1.9.',
+ PendingDeprecationWarning
+ )
# Load all the ALWAYS_INSTALLED_APPS.
django.setup()
@@ -169,8 +174,8 @@ def setup(verbosity, test_labels):
if module_label not in settings.INSTALLED_APPS:
settings.INSTALLED_APPS.append(module_label)
app_config = AppConfig.create(module_label)
- app_config.import_models(apps.all_models[app_config.label])
apps.app_configs[app_config.label] = app_config
+ app_config.import_models(apps.all_models[app_config.label])
apps.clear_cache()
return state