summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/db/models/base.py14
-rw-r--r--django/db/models/manager.py17
2 files changed, 24 insertions, 7 deletions
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 #
#######################