From e2dfad15f14f4da61ec7bcfc5cab2b083fd7ec63 Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Thu, 20 Mar 2008 16:10:51 +0000 Subject: [PATCH] queyrset-refactor: Allow default managers to be inherited from an abstract base class, unless the child class defines its own manager (i.e. child has first chance to define the default). All managers were already inherited. This just changes how the default is set in the case when the child defines no manager and an abstract parent does. git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@7339 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/models/base.py | 14 +++++++++----- django/db/models/manager.py | 17 +++++++++++++++-- 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 # #######################