Loading django/db/migrations/state.py +1 −2 Original line number Diff line number Diff line Loading @@ -500,8 +500,7 @@ class ModelState(object): else: # Force this manager to be the first and thus default managers_mapping[default_manager_name] = (0, models.Manager()) # Sort all managers by their creation counter for _, manager, _ in sorted(model._meta.managers): for manager in model._meta.managers: if manager.name == "_base_manager" or not manager.use_in_migrations: continue reconstruct_manager(manager) Loading django/db/models/base.py +2 −31 Original line number Diff line number Diff line Loading @@ -151,18 +151,6 @@ class ModelBase(type): if is_proxy and base_meta and base_meta.swapped: raise TypeError("%s cannot proxy the swapped model '%s'." % (name, base_meta.swapped)) if getattr(new_class, '_default_manager', None): if not is_proxy: # Multi-table inheritance doesn't inherit default manager from # parents. new_class._default_manager = None new_class._base_manager = None else: # Proxy classes do inherit parent's default manager, if none is # set explicitly. 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) # Add all attributes to the class. for obj_name, obj in attrs.items(): new_class.add_to_class(obj_name, obj) Loading Loading @@ -217,7 +205,6 @@ class ModelBase(type): inherited_attributes = set() # Do the appropriate setup for any model parents. for base in new_class.mro(): original_base = base if base not in parents or not hasattr(base, '_meta'): # Things without _meta aren't functional models, so they're # uninteresting parents. Loading Loading @@ -294,14 +281,6 @@ class ModelBase(type): # Pass any non-abstract parent classes onto child. new_class._meta.parents.update(base_parents) # Inherit managers from the abstract base classes. new_class.copy_managers(base._meta.abstract_managers) # Proxy models inherit the non-abstract managers from their base, # unless they have redefined any of them. if is_proxy: new_class.copy_managers(original_base._meta.concrete_managers) # Inherit private fields (like GenericForeignKey) from the parent # class for field in base._meta.private_fields: Loading Loading @@ -330,15 +309,6 @@ class ModelBase(type): new_class._meta.apps.register_model(new_class._meta.app_label, new_class) return new_class def copy_managers(cls, base_managers): # This is in-place sorting of an Options attribute, but that's fine. base_managers.sort() for _, mgr_name, manager in base_managers: # NOQA (redefinition of _) val = getattr(cls, mgr_name, None) if not val or val is manager: new_manager = manager._copy_to_model(cls) cls.add_to_class(mgr_name, new_manager) def add_to_class(cls, name, value): # We should call the contribute_to_class method only if it's bound if not inspect.isclass(value) and hasattr(value, 'contribute_to_class'): Loading Loading @@ -376,6 +346,7 @@ class ModelBase(type): setattr(cls, 'get_absolute_url', get_absolute_url_override) ensure_default_manager(cls) signals.class_prepared.send(sender=cls) Loading Loading @@ -1263,7 +1234,7 @@ class Model(six.with_metaclass(ModelBase)): """ Perform all manager checks. """ errors = [] for __, manager, __ in cls._meta.managers: for manager in cls._meta.managers: errors.extend(manager.check(**kwargs)) return errors Loading django/db/models/manager.py +47 −91 Original line number Diff line number Diff line Loading @@ -8,43 +8,40 @@ from django.utils import six from django.utils.encoding import python_2_unicode_compatible def ensure_default_manager(cls): def can_use_for_related_field(manager_class): return manager_class is Manager or getattr(manager_class, 'use_for_related_fields', False) def ensure_default_manager(model): """ Ensures that a Model subclass contains a default manager and sets the _default_manager attribute on the class. Also sets up the _base_manager points to a plain Manager instance (which could be the same as _default_manager if it's not a subclass of Manager). _default_manager and _base_manager attributes on the class. """ if cls._meta.swapped: setattr(cls, 'objects', SwappedManagerDescriptor(cls)) return if not getattr(cls, '_default_manager', None): if any(f.name == 'objects' for f in cls._meta.fields): if not model._meta.managers: if any(f.name == 'objects' for f in model._meta.fields): raise ValueError( "Model %s must specify a custom Manager, because it has a " "field named 'objects'" % cls.__name__ "field named 'objects'" % model.__name__ ) # Create the default manager, if needed. cls.add_to_class('objects', Manager()) cls._base_manager = cls.objects elif not getattr(cls, '_base_manager', None): default_mgr = cls._default_manager.__class__ if (default_mgr is Manager or getattr(default_mgr, "use_for_related_fields", False)): cls._base_manager = cls._default_manager model.add_to_class('objects', Manager()) model._default_manager = model._meta.managers[0] # Just alias _base_manager if default manager is suitable. if can_use_for_related_field(model._default_manager.__class__): model._base_manager = model._default_manager # Otherwise search for a suitable manager type in the default manager MRO. else: # Default manager isn't a plain Manager class, or a suitable # replacement, so we walk up the base class hierarchy until we hit # something appropriate. for base_class in default_mgr.mro()[1:]: if (base_class is Manager or getattr(base_class, "use_for_related_fields", False)): cls.add_to_class('_base_manager', base_class()) return raise AssertionError( "Should never get here. Please report a bug, including your " "model and model manager setup." ) for base_manager_class in model._default_manager.__class__.mro()[1:]: if can_use_for_related_field(base_manager_class): model._base_manager = base_manager_class() model._base_manager.name = '_base_manager' model._base_manager.model = model break else: raise ValueError("Could not find a suitable base manager.") @python_2_unicode_compatible Loading @@ -67,7 +64,6 @@ class BaseManager(object): self._set_creation_counter() self.model = None self.name = None self._inherited = False self._db = None self._hints = {} Loading Loading @@ -150,26 +146,13 @@ class BaseManager(object): return type(class_name, (cls,), class_dict) 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)) elif model._meta.swapped: setattr(model, name, SwappedManagerDescriptor(model)) else: # if not model._meta.abstract and not model._meta.swapped: self.model = model setattr(model, name, ManagerDescriptor(self)) 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): abstract = True model._meta.managers.append((self.creation_counter, self, abstract)) model._meta.add_manager(self) def _set_creation_counter(self): """ Loading @@ -179,19 +162,6 @@ class BaseManager(object): self.creation_counter = BaseManager.creation_counter BaseManager.creation_counter += 1 def _copy_to_model(self, model): """ Makes a copy of the manager and assigns it to 'model', which should be a child of the existing model (used when inheriting a manager from an abstract base class). """ assert issubclass(model, self.model) mgr = copy.copy(self) mgr._set_creation_counter() mgr.model = model mgr._inherited = True return mgr def db_manager(self, using=None, hints=None): obj = copy.copy(self) obj._db = using or self._db Loading Loading @@ -240,44 +210,30 @@ class Manager(BaseManager.from_queryset(QuerySet)): class ManagerDescriptor(object): # This class ensures managers aren't accessible via model instances. # For example, Poll.objects works, but poll_obj.objects raises AttributeError. def __init__(self, manager): self.manager = manager def __get__(self, instance, cls=None): if instance is not None: raise AttributeError("Manager isn't accessible via %s instances" % cls.__name__) return self.manager class AbstractManagerDescriptor(object): # This class provides a better error message when you try to access a # manager on an abstract model. def __init__(self, model): self.model = model def __get__(self, instance, cls=None): if cls._meta.abstract: raise AttributeError("Manager isn't available; %s is abstract" % ( self.model._meta.object_name, cls._meta.object_name, )) class SwappedManagerDescriptor(object): # This class provides a better error message when you try to access a # manager on a swapped model. def __init__(self, model): self.model = model def __get__(self, instance, cls=None): if cls._meta.swapped: raise AttributeError( "Manager isn't available; '%s.%s' has been swapped for '%s'" % ( self.model._meta.app_label, self.model._meta.object_name, self.model._meta.swapped, cls._meta.app_label, cls._meta.object_name, cls._meta.swapped, ) ) return cls._meta.managers_map[self.manager.name] class EmptyManager(Manager): def __init__(self, model): Loading django/db/models/options.py +27 −21 Original line number Diff line number Diff line from __future__ import unicode_literals import copy import warnings from bisect import bisect from collections import OrderedDict, defaultdict Loading Loading @@ -73,7 +74,8 @@ def make_immutable_fields_list(name, data): @python_2_unicode_compatible class Options(object): FORWARD_PROPERTIES = {'fields', 'many_to_many', 'concrete_fields', 'local_concrete_fields', '_forward_fields_map'} 'local_concrete_fields', '_forward_fields_map', 'managers', 'managers_map'} REVERSE_PROPERTIES = {'related_objects', 'fields_map', '_relation_tree'} default_apps = apps Loading @@ -83,6 +85,7 @@ class Options(object): self.local_fields = [] self.local_many_to_many = [] self.private_fields = [] self.local_managers = [] self.model_name = None self.verbose_name = None self.verbose_name_plural = None Loading Loading @@ -122,12 +125,6 @@ class Options(object): self.parents = OrderedDict() self.auto_created = False # To handle various inheritance situations, we need to track where # 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. self.related_fkey_lookups = [] Loading @@ -154,20 +151,6 @@ 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 Loading Loading @@ -264,6 +247,10 @@ class Options(object): auto = AutoField(verbose_name='ID', primary_key=True, auto_created=True) model.add_to_class('id', auto) def add_manager(self, manager): self.local_managers.append(manager) self._expire_cache() def add_field(self, field, private=False, virtual=NOT_PROVIDED): if virtual is not NOT_PROVIDED: warnings.warn( Loading Loading @@ -371,6 +358,25 @@ class Options(object): return swapped_for return None @cached_property def managers(self): managers = [] bases = (b for b in self.model.mro() if hasattr(b, '_meta')) for depth, base in enumerate(bases): for manager in base._meta.local_managers: manager = copy.copy(manager) manager.model = self.model managers.append((depth, manager.creation_counter, manager)) return make_immutable_fields_list( "managers", (m[2] for m in sorted(managers)), ) @cached_property def managers_map(self): return {manager.name: manager for manager in reversed(self.managers)} @cached_property def fields(self): """ Loading docs/topics/db/managers.txt +17 −24 Original line number Diff line number Diff line Loading @@ -321,33 +321,26 @@ You may also store the generated class into a variable:: Custom managers and model inheritance ------------------------------------- Class inheritance and model managers aren't quite a perfect match for each other. Managers are often specific to the classes they are defined on and inheriting them in subclasses isn't necessarily a good idea. Also, because the first manager declared is the *default manager*, it is important to allow that to be controlled. So here's how Django handles custom managers and Here's how Django handles custom managers and :ref:`model inheritance <model-inheritance>`: 1. Managers defined on non-abstract base classes are *not* inherited by child classes. If you want to reuse a manager from a non-abstract base, redeclare it explicitly on the child class. These sorts of managers are likely to be fairly specific to the class they are defined on, so inheriting them can often lead to unexpected results (particularly as far as the default manager goes). Therefore, they aren't passed onto child classes. 2. Managers from abstract base classes are always inherited by the child class, using Python's normal name resolution order (names on the child 1. Managers from base classes are always inherited by the child class, using Python's normal name resolution order (names on the child class override all others; then come names on the first parent class, and so on). Abstract base classes are designed to capture information and behavior that is common to their child classes. Defining common managers is an appropriate part of this common information. 3. The default manager on a class is either the first manager declared on the class, if that exists, or the default manager of the first abstract base class in the parent hierarchy, if that exists. If no default manager is explicitly declared, Django's normal default manager is used. and so on). 2. The default manager on a class is either the first manager declared on the class, if that exists, or the default manager of the first parent class in the parent hierarchy, if that exists. If no manager is explicitly declared, Django automatically creates the `objects` manager and it becomes the default manager. .. versionchanged:: 1.10 In older versions, manager inheritance varied depending on the type of model inheritance (i.e. :ref:`abstract-base-classes`, :ref:`multi-table-inheritance`, or :ref:`proxy-models`), especially with regards to electing the default manager. These rules provide the necessary flexibility if you want to install a collection of custom managers on a group of models, via an abstract base Loading Loading
django/db/migrations/state.py +1 −2 Original line number Diff line number Diff line Loading @@ -500,8 +500,7 @@ class ModelState(object): else: # Force this manager to be the first and thus default managers_mapping[default_manager_name] = (0, models.Manager()) # Sort all managers by their creation counter for _, manager, _ in sorted(model._meta.managers): for manager in model._meta.managers: if manager.name == "_base_manager" or not manager.use_in_migrations: continue reconstruct_manager(manager) Loading
django/db/models/base.py +2 −31 Original line number Diff line number Diff line Loading @@ -151,18 +151,6 @@ class ModelBase(type): if is_proxy and base_meta and base_meta.swapped: raise TypeError("%s cannot proxy the swapped model '%s'." % (name, base_meta.swapped)) if getattr(new_class, '_default_manager', None): if not is_proxy: # Multi-table inheritance doesn't inherit default manager from # parents. new_class._default_manager = None new_class._base_manager = None else: # Proxy classes do inherit parent's default manager, if none is # set explicitly. 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) # Add all attributes to the class. for obj_name, obj in attrs.items(): new_class.add_to_class(obj_name, obj) Loading Loading @@ -217,7 +205,6 @@ class ModelBase(type): inherited_attributes = set() # Do the appropriate setup for any model parents. for base in new_class.mro(): original_base = base if base not in parents or not hasattr(base, '_meta'): # Things without _meta aren't functional models, so they're # uninteresting parents. Loading Loading @@ -294,14 +281,6 @@ class ModelBase(type): # Pass any non-abstract parent classes onto child. new_class._meta.parents.update(base_parents) # Inherit managers from the abstract base classes. new_class.copy_managers(base._meta.abstract_managers) # Proxy models inherit the non-abstract managers from their base, # unless they have redefined any of them. if is_proxy: new_class.copy_managers(original_base._meta.concrete_managers) # Inherit private fields (like GenericForeignKey) from the parent # class for field in base._meta.private_fields: Loading Loading @@ -330,15 +309,6 @@ class ModelBase(type): new_class._meta.apps.register_model(new_class._meta.app_label, new_class) return new_class def copy_managers(cls, base_managers): # This is in-place sorting of an Options attribute, but that's fine. base_managers.sort() for _, mgr_name, manager in base_managers: # NOQA (redefinition of _) val = getattr(cls, mgr_name, None) if not val or val is manager: new_manager = manager._copy_to_model(cls) cls.add_to_class(mgr_name, new_manager) def add_to_class(cls, name, value): # We should call the contribute_to_class method only if it's bound if not inspect.isclass(value) and hasattr(value, 'contribute_to_class'): Loading Loading @@ -376,6 +346,7 @@ class ModelBase(type): setattr(cls, 'get_absolute_url', get_absolute_url_override) ensure_default_manager(cls) signals.class_prepared.send(sender=cls) Loading Loading @@ -1263,7 +1234,7 @@ class Model(six.with_metaclass(ModelBase)): """ Perform all manager checks. """ errors = [] for __, manager, __ in cls._meta.managers: for manager in cls._meta.managers: errors.extend(manager.check(**kwargs)) return errors Loading
django/db/models/manager.py +47 −91 Original line number Diff line number Diff line Loading @@ -8,43 +8,40 @@ from django.utils import six from django.utils.encoding import python_2_unicode_compatible def ensure_default_manager(cls): def can_use_for_related_field(manager_class): return manager_class is Manager or getattr(manager_class, 'use_for_related_fields', False) def ensure_default_manager(model): """ Ensures that a Model subclass contains a default manager and sets the _default_manager attribute on the class. Also sets up the _base_manager points to a plain Manager instance (which could be the same as _default_manager if it's not a subclass of Manager). _default_manager and _base_manager attributes on the class. """ if cls._meta.swapped: setattr(cls, 'objects', SwappedManagerDescriptor(cls)) return if not getattr(cls, '_default_manager', None): if any(f.name == 'objects' for f in cls._meta.fields): if not model._meta.managers: if any(f.name == 'objects' for f in model._meta.fields): raise ValueError( "Model %s must specify a custom Manager, because it has a " "field named 'objects'" % cls.__name__ "field named 'objects'" % model.__name__ ) # Create the default manager, if needed. cls.add_to_class('objects', Manager()) cls._base_manager = cls.objects elif not getattr(cls, '_base_manager', None): default_mgr = cls._default_manager.__class__ if (default_mgr is Manager or getattr(default_mgr, "use_for_related_fields", False)): cls._base_manager = cls._default_manager model.add_to_class('objects', Manager()) model._default_manager = model._meta.managers[0] # Just alias _base_manager if default manager is suitable. if can_use_for_related_field(model._default_manager.__class__): model._base_manager = model._default_manager # Otherwise search for a suitable manager type in the default manager MRO. else: # Default manager isn't a plain Manager class, or a suitable # replacement, so we walk up the base class hierarchy until we hit # something appropriate. for base_class in default_mgr.mro()[1:]: if (base_class is Manager or getattr(base_class, "use_for_related_fields", False)): cls.add_to_class('_base_manager', base_class()) return raise AssertionError( "Should never get here. Please report a bug, including your " "model and model manager setup." ) for base_manager_class in model._default_manager.__class__.mro()[1:]: if can_use_for_related_field(base_manager_class): model._base_manager = base_manager_class() model._base_manager.name = '_base_manager' model._base_manager.model = model break else: raise ValueError("Could not find a suitable base manager.") @python_2_unicode_compatible Loading @@ -67,7 +64,6 @@ class BaseManager(object): self._set_creation_counter() self.model = None self.name = None self._inherited = False self._db = None self._hints = {} Loading Loading @@ -150,26 +146,13 @@ class BaseManager(object): return type(class_name, (cls,), class_dict) 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)) elif model._meta.swapped: setattr(model, name, SwappedManagerDescriptor(model)) else: # if not model._meta.abstract and not model._meta.swapped: self.model = model setattr(model, name, ManagerDescriptor(self)) 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): abstract = True model._meta.managers.append((self.creation_counter, self, abstract)) model._meta.add_manager(self) def _set_creation_counter(self): """ Loading @@ -179,19 +162,6 @@ class BaseManager(object): self.creation_counter = BaseManager.creation_counter BaseManager.creation_counter += 1 def _copy_to_model(self, model): """ Makes a copy of the manager and assigns it to 'model', which should be a child of the existing model (used when inheriting a manager from an abstract base class). """ assert issubclass(model, self.model) mgr = copy.copy(self) mgr._set_creation_counter() mgr.model = model mgr._inherited = True return mgr def db_manager(self, using=None, hints=None): obj = copy.copy(self) obj._db = using or self._db Loading Loading @@ -240,44 +210,30 @@ class Manager(BaseManager.from_queryset(QuerySet)): class ManagerDescriptor(object): # This class ensures managers aren't accessible via model instances. # For example, Poll.objects works, but poll_obj.objects raises AttributeError. def __init__(self, manager): self.manager = manager def __get__(self, instance, cls=None): if instance is not None: raise AttributeError("Manager isn't accessible via %s instances" % cls.__name__) return self.manager class AbstractManagerDescriptor(object): # This class provides a better error message when you try to access a # manager on an abstract model. def __init__(self, model): self.model = model def __get__(self, instance, cls=None): if cls._meta.abstract: raise AttributeError("Manager isn't available; %s is abstract" % ( self.model._meta.object_name, cls._meta.object_name, )) class SwappedManagerDescriptor(object): # This class provides a better error message when you try to access a # manager on a swapped model. def __init__(self, model): self.model = model def __get__(self, instance, cls=None): if cls._meta.swapped: raise AttributeError( "Manager isn't available; '%s.%s' has been swapped for '%s'" % ( self.model._meta.app_label, self.model._meta.object_name, self.model._meta.swapped, cls._meta.app_label, cls._meta.object_name, cls._meta.swapped, ) ) return cls._meta.managers_map[self.manager.name] class EmptyManager(Manager): def __init__(self, model): Loading
django/db/models/options.py +27 −21 Original line number Diff line number Diff line from __future__ import unicode_literals import copy import warnings from bisect import bisect from collections import OrderedDict, defaultdict Loading Loading @@ -73,7 +74,8 @@ def make_immutable_fields_list(name, data): @python_2_unicode_compatible class Options(object): FORWARD_PROPERTIES = {'fields', 'many_to_many', 'concrete_fields', 'local_concrete_fields', '_forward_fields_map'} 'local_concrete_fields', '_forward_fields_map', 'managers', 'managers_map'} REVERSE_PROPERTIES = {'related_objects', 'fields_map', '_relation_tree'} default_apps = apps Loading @@ -83,6 +85,7 @@ class Options(object): self.local_fields = [] self.local_many_to_many = [] self.private_fields = [] self.local_managers = [] self.model_name = None self.verbose_name = None self.verbose_name_plural = None Loading Loading @@ -122,12 +125,6 @@ class Options(object): self.parents = OrderedDict() self.auto_created = False # To handle various inheritance situations, we need to track where # 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. self.related_fkey_lookups = [] Loading @@ -154,20 +151,6 @@ 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 Loading Loading @@ -264,6 +247,10 @@ class Options(object): auto = AutoField(verbose_name='ID', primary_key=True, auto_created=True) model.add_to_class('id', auto) def add_manager(self, manager): self.local_managers.append(manager) self._expire_cache() def add_field(self, field, private=False, virtual=NOT_PROVIDED): if virtual is not NOT_PROVIDED: warnings.warn( Loading Loading @@ -371,6 +358,25 @@ class Options(object): return swapped_for return None @cached_property def managers(self): managers = [] bases = (b for b in self.model.mro() if hasattr(b, '_meta')) for depth, base in enumerate(bases): for manager in base._meta.local_managers: manager = copy.copy(manager) manager.model = self.model managers.append((depth, manager.creation_counter, manager)) return make_immutable_fields_list( "managers", (m[2] for m in sorted(managers)), ) @cached_property def managers_map(self): return {manager.name: manager for manager in reversed(self.managers)} @cached_property def fields(self): """ Loading
docs/topics/db/managers.txt +17 −24 Original line number Diff line number Diff line Loading @@ -321,33 +321,26 @@ You may also store the generated class into a variable:: Custom managers and model inheritance ------------------------------------- Class inheritance and model managers aren't quite a perfect match for each other. Managers are often specific to the classes they are defined on and inheriting them in subclasses isn't necessarily a good idea. Also, because the first manager declared is the *default manager*, it is important to allow that to be controlled. So here's how Django handles custom managers and Here's how Django handles custom managers and :ref:`model inheritance <model-inheritance>`: 1. Managers defined on non-abstract base classes are *not* inherited by child classes. If you want to reuse a manager from a non-abstract base, redeclare it explicitly on the child class. These sorts of managers are likely to be fairly specific to the class they are defined on, so inheriting them can often lead to unexpected results (particularly as far as the default manager goes). Therefore, they aren't passed onto child classes. 2. Managers from abstract base classes are always inherited by the child class, using Python's normal name resolution order (names on the child 1. Managers from base classes are always inherited by the child class, using Python's normal name resolution order (names on the child class override all others; then come names on the first parent class, and so on). Abstract base classes are designed to capture information and behavior that is common to their child classes. Defining common managers is an appropriate part of this common information. 3. The default manager on a class is either the first manager declared on the class, if that exists, or the default manager of the first abstract base class in the parent hierarchy, if that exists. If no default manager is explicitly declared, Django's normal default manager is used. and so on). 2. The default manager on a class is either the first manager declared on the class, if that exists, or the default manager of the first parent class in the parent hierarchy, if that exists. If no manager is explicitly declared, Django automatically creates the `objects` manager and it becomes the default manager. .. versionchanged:: 1.10 In older versions, manager inheritance varied depending on the type of model inheritance (i.e. :ref:`abstract-base-classes`, :ref:`multi-table-inheritance`, or :ref:`proxy-models`), especially with regards to electing the default manager. These rules provide the necessary flexibility if you want to install a collection of custom managers on a group of models, via an abstract base Loading