summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAymeric Augustin <aymeric.augustin@m4x.org>2014-01-05 09:32:22 +0100
committerAymeric Augustin <aymeric.augustin@m4x.org>2014-01-05 20:52:53 +0100
commitf630373b929bc62bf4d66d60c532f7832e5fbe67 (patch)
treeb75eb1b0dd872d60b7f973889ca40883a620fe35
parentf5f761716731ceedaf165a068e6f88164cd87e79 (diff)
Fixed #21711 -- Enforced unicity of model names.
-rw-r--r--django/apps/registry.py1
-rw-r--r--django/db/models/base.py13
-rw-r--r--django/db/models/query_utils.py27
-rw-r--r--docs/releases/1.7.txt6
4 files changed, 24 insertions, 23 deletions
diff --git a/django/apps/registry.py b/django/apps/registry.py
index db75f999c5..f88fb73dd6 100644
--- a/django/apps/registry.py
+++ b/django/apps/registry.py
@@ -185,7 +185,6 @@ class Apps(object):
# call get_app_config().
model_name = model._meta.model_name
app_models = self.all_models[app_label]
- # Defensive check for extra safety.
if model_name in app_models:
raise RuntimeError(
"Conflicting '%s' models in application '%s': %s and %s." %
diff --git a/django/db/models/base.py b/django/db/models/base.py
index 0de21fafc9..531dd8adcc 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -162,12 +162,6 @@ class ModelBase(type):
new_class._default_manager = new_class._default_manager._copy_to_model(new_class)
new_class._base_manager = new_class._base_manager._copy_to_model(new_class)
- # Bail out early if we have already created this class.
- try:
- return new_class._meta.apps.get_registered_model(new_class._meta.app_label, name)
- except LookupError:
- pass
-
# Add all attributes to the class.
for obj_name, obj in attrs.items():
new_class.add_to_class(obj_name, obj)
@@ -285,13 +279,8 @@ class ModelBase(type):
return new_class
new_class._prepare()
-
new_class._meta.apps.register_model(new_class._meta.app_label, new_class)
- # Because of the way imports happen (recursively), we may or may not be
- # the first time this model tries to register with the framework. There
- # should only be one class for each model, so we always return the
- # registered version.
- return new_class._meta.apps.get_registered_model(new_class._meta.app_label, name)
+ return new_class
def copy_managers(cls, base_managers):
# This is in-place sorting of an Options attribute, but that's fine.
diff --git a/django/db/models/query_utils.py b/django/db/models/query_utils.py
index 2aa4856cf0..b6971e9f24 100644
--- a/django/db/models/query_utils.py
+++ b/django/db/models/query_utils.py
@@ -7,6 +7,7 @@ circular import difficulties.
"""
from __future__ import unicode_literals
+from django.apps import apps
from django.db.backends import utils
from django.utils import six
from django.utils import tree
@@ -185,22 +186,28 @@ def deferred_class_factory(model, attrs):
being replaced with DeferredAttribute objects. The "pk_value" ties the
deferred attributes to a particular instance of the model.
"""
- class Meta:
- proxy = True
- app_label = model._meta.app_label
-
# The app registry wants a unique name for each model, otherwise the new
- # class won't be created (we get an old one back). Therefore, we generate
+ # class won't be created (we get an exception). Therefore, we generate
# the name using the passed in attrs. It's OK to reuse an existing class
# object if the attrs are identical.
name = "%s_Deferred_%s" % (model.__name__, '_'.join(sorted(list(attrs))))
name = utils.truncate_name(name, 80, 32)
- overrides = dict((attr, DeferredAttribute(attr, model)) for attr in attrs)
- overrides["Meta"] = Meta
- overrides["__module__"] = model.__module__
- overrides["_deferred"] = True
- return type(str(name), (model,), overrides)
+ try:
+ return apps.get_model(model._meta.app_label, name)
+
+ except LookupError:
+
+ class Meta:
+ proxy = True
+ app_label = model._meta.app_label
+
+ overrides = dict((attr, DeferredAttribute(attr, model)) for attr in attrs)
+ overrides["Meta"] = Meta
+ overrides["__module__"] = model.__module__
+ overrides["_deferred"] = True
+ return type(str(name), (model,), overrides)
+
# The above function is also used to unpickle model instances with deferred
# fields.
diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt
index c684454181..a4b230510a 100644
--- a/docs/releases/1.7.txt
+++ b/docs/releases/1.7.txt
@@ -664,6 +664,12 @@ If you have two apps with the same label, you should create an
:class:`~django.apps.AppConfig.label` there. You should then adjust your code
wherever it references this application or its models with the old label.
+It isn't possible to import the same model twice through different paths any
+more. As of Django 1.6, this may happen only if you're manually putting a
+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.