diff --git a/django/db/models/base.py b/django/db/models/base.py index 0d06ca5727..02c5398fb1 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -3,8 +3,8 @@ import sys import os from itertools import izip -import django.db.models.manipulators -import django.db.models.manager +import django.db.models.manipulators # Imported to register signal handler. +import django.db.models.manager # Ditto. from django.core import validators from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError from django.db.models.fields import AutoField, ImageField, FieldDoesNotExist @@ -59,9 +59,11 @@ class ModelBase(type): if not hasattr(meta, 'get_latest_by'): new_class._meta.get_latest_by = base_meta.get_latest_by - if getattr(new_class, '_default_manager', None) is not None: - # We have a parent who set the default manager. We need to override - # this. + old_default_mgr = None + if getattr(new_class, '_default_manager', None): + # We have a parent who set the default manager. + if new_class._default_manager.model._meta.abstract: + old_default_mgr = new_class._default_manager new_class._default_manager = None if getattr(new_class._meta, 'app_label', None) is None: # Figure out the app_label by looking one level up. @@ -113,6 +115,8 @@ class ModelBase(type): new_class.Meta = attr_meta return new_class + if old_default_mgr and not new_class._default_manager: + new_class._default_manager = old_default_mgr._copy_to_model(new_class) new_class._prepare() register_models(new_class._meta.app_label, new_class) diff --git a/django/db/models/manager.py b/django/db/models/manager.py index 3a2efe84a8..1e2cd58850 100644 --- a/django/db/models/manager.py +++ b/django/db/models/manager.py @@ -1,3 +1,5 @@ +import copy + from django.db.models.query import QuerySet, EmptyQuerySet, insert_query from django.dispatch import dispatcher from django.db.models import signals @@ -5,7 +7,7 @@ from django.db.models.fields import FieldDoesNotExist def ensure_default_manager(sender): cls = sender - if not hasattr(cls, '_default_manager') or cls._default_manager is None: + if not getattr(cls, '_default_manager', None) and not cls._meta.abstract: # Create the default manager, if needed. try: cls._meta.get_field('objects') @@ -31,9 +33,20 @@ class Manager(object): # TODO: Use weakref because of possible memory leak / circular reference. self.model = model setattr(model, name, ManagerDescriptor(self)) - if not hasattr(model, '_default_manager') or model._default_manager is None or self.creation_counter < model._default_manager.creation_counter: + if not getattr(model, '_default_manager', None) or self.creation_counter < model._default_manager.creation_counter: model._default_manager = self + 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.model = model + return mgr + ####################### # PROXIES TO QUERYSET # #######################