Commit f630373b authored by Aymeric Augustin's avatar Aymeric Augustin
Browse files

Fixed #21711 -- Enforced unicity of model names.

parent f5f76171
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -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." %
+1 −12
Original line number Diff line number Diff line
@@ -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.
+17 −10
Original line number Diff line number Diff line
@@ -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,23 +186,29 @@ 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)

    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.
deferred_class_factory.__safe_for_unpickling__ = True
+6 −0
Original line number Diff line number Diff line
@@ -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.