Fix Django 1.5 support, tests pass again.

The reason polymorphic broke was because it couldn't find some managers
anymore in the inheritance tree. Django 1.5 removes these and replaces
them with an `AbstractManagerDescriptor`. This patch restores those objects
fix_request_path_info
Diederik van der Boor 2013-04-07 00:28:57 +02:00
parent ca4067e279
commit 1f26302632
2 changed files with 28 additions and 3 deletions

View File

@ -16,6 +16,11 @@ from query import PolymorphicQuerySet
# These are forbidden as field names (a descriptive exception is raised)
POLYMORPHIC_SPECIAL_Q_KWORDS = ['instance_of', 'not_instance_of']
try:
from django.db.models.manager import AbstractManagerDescriptor # Django 1.5
except ImportError:
AbstractManagerDescriptor = None
###################################################################################
### PolymorphicModel meta class
@ -91,6 +96,7 @@ class PolymorphicModelBase(ModelBase):
use correct mro, only use managers with _inherited==False (they are of no use),
skip managers that are overwritten by the user with same-named class attributes (in attrs)
"""
#print "** ", self.__name__
add_managers = []
add_managers_keys = set()
for base in self.__mro__[1:]:
@ -102,9 +108,23 @@ class PolymorphicModelBase(ModelBase):
for key, manager in base.__dict__.items():
if type(manager) == models.manager.ManagerDescriptor:
manager = manager.manager
if AbstractManagerDescriptor is not None:
# Django 1.4 unconditionally assigned managers to a model. As of Django 1.5 however,
# the abstract models don't get any managers, only a AbstractManagerDescriptor as substitute.
# Pretend that the manager is still there, so all code works like it used to.
if type(manager) == AbstractManagerDescriptor and base.__name__ == 'PolymorphicModel':
model = manager.model
if key == 'objects':
manager = PolymorphicManager()
manager.model = model
elif key == 'base_objects':
manager = models.Manager()
manager.model = model
if not isinstance(manager, models.Manager):
continue
if key in ['_base_manager']:
if key == '_base_manager':
continue # let Django handle _base_manager
if key in attrs:
continue
@ -112,7 +132,8 @@ class PolymorphicModelBase(ModelBase):
continue # manager with that name already added, skip
if manager._inherited:
continue # inherited managers (on the bases) have no significance, they are just copies
#print >>sys.stderr,'##',self.__name__, key
#print '## {0} {1}'.format(self.__name__, key)
if isinstance(manager, PolymorphicManager): # validate any inherited polymorphic managers
self.validate_model_manager(manager, self.__name__, key)
add_managers.append((base.__name__, key, manager))
@ -121,16 +142,18 @@ class PolymorphicModelBase(ModelBase):
@classmethod
def get_first_user_defined_manager(self):
# See if there is a manager attribute directly stored at this inheritance level.
mgr_list = []
for key, val in self.__dict__.items():
item = getattr(self, key)
if not isinstance(item, models.Manager): continue
mgr_list.append((item.creation_counter, key, item))
# if there are user defined managers, use first one as _default_manager
if mgr_list:
_, manager_name, manager = sorted(mgr_list)[0]
#sys.stderr.write( '\n# first user defined manager for model "{model}":\n# "{mgrname}": {mgr}\n# manager model: {mgrmodel}\n\n'
# .format( model=model_name, mgrname=manager_name, mgr=manager, mgrmodel=manager.model ) )
# .format( model=self.__name__, mgrname=manager_name, mgr=manager, mgrmodel=manager.model ) )
return manager
return None

View File

@ -67,6 +67,8 @@ class PolymorphicModel(models.Model):
# some applications want to know the name of the fields that are added to its models
polymorphic_internal_model_fields = ['polymorphic_ctype']
# Note that Django 1.5 removes these managers because the model is abstract.
# They are pretended to be there by the metaclass in PolymorphicModelBase.get_inherited_managers()
objects = PolymorphicManager()
base_objects = models.Manager()