Commit e37ab311 authored by Markus Holtermann's avatar Markus Holtermann Committed by Tim Graham
Browse files

Changed internal storing of abstract and concrete managers to be in a single list.

This commit prepares the internal manager layout to be serialized by
migrations; refs #23822.
parent 7c1f3901
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -1225,8 +1225,7 @@ class Model(six.with_metaclass(ModelBase)):
        """ Perform all manager checks. """

        errors = []
        managers = cls._meta.concrete_managers + cls._meta.abstract_managers
        for __, __, manager in managers:
        for __, manager, __ in cls._meta.managers:
            errors.extend(manager.check(**kwargs))
        return errors

+8 −10
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ class BaseManager(object):
        super(BaseManager, self).__init__()
        self._set_creation_counter()
        self.model = None
        self.name = None
        self._inherited = False
        self._db = None
        self._hints = {}
@@ -69,12 +70,8 @@ class BaseManager(object):
    def __str__(self):
        """ Return "app_label.model_label.manager_name". """
        model = self.model
        opts = model._meta
        app = model._meta.app_label
        manager_name = next(name for (_, name, manager)
            in opts.concrete_managers + opts.abstract_managers
            if manager == self)
        return '%s.%s.%s' % (app, model._meta.object_name, manager_name)
        return '%s.%s.%s' % (app, model._meta.object_name, self.name)

    def check(self, **kwargs):
        return []
@@ -116,6 +113,8 @@ class BaseManager(object):
    def contribute_to_class(self, model, name):
        # TODO: Use weakref because of possible memory leak / circular reference.
        self.model = model
        if not self.name:
            self.name = name
        # Only contribute the manager if the model is concrete
        if model._meta.abstract:
            setattr(model, name, AbstractManagerDescriptor(model))
@@ -127,12 +126,11 @@ class BaseManager(object):
        if (not getattr(model, '_default_manager', None) or
                self.creation_counter < model._default_manager.creation_counter):
            model._default_manager = self

        abstract = False
        if model._meta.abstract or (self._inherited and not self.model._meta.proxy):
            model._meta.abstract_managers.append((self.creation_counter, name,
                    self))
        else:
            model._meta.concrete_managers.append((self.creation_counter, name,
                self))
            abstract = True
        model._meta.managers.append((self.creation_counter, self, abstract))

    def _set_creation_counter(self):
        """
+18 −3
Original line number Diff line number Diff line
@@ -88,9 +88,10 @@ class Options(object):
        self.auto_created = False

        # To handle various inheritance situations, we need to track where
        # managers came from (concrete or abstract base classes).
        self.abstract_managers = []
        self.concrete_managers = []
        # managers came from (concrete or abstract base classes). `managers`
        # keeps a list of 3-tuples of the form:
        # (creation_counter, instance, abstract(=True))
        self.managers = []

        # List of all lookups defined in ForeignKey 'limit_choices_to' options
        # from *other* models. Needed for some admin checks. Internal use only.
@@ -110,6 +111,20 @@ class Options(object):
    def installed(self):
        return self.app_config is not None

    @property
    def abstract_managers(self):
        return [
            (counter, instance.name, instance) for counter, instance, abstract
            in self.managers if abstract
        ]

    @property
    def concrete_managers(self):
        return [
            (counter, instance.name, instance) for counter, instance, abstract
            in self.managers if not abstract
        ]

    def contribute_to_class(self, cls, name):
        from django.db import connection
        from django.db.backends.utils import truncate_name