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) # These are forbidden as field names (a descriptive exception is raised)
POLYMORPHIC_SPECIAL_Q_KWORDS = ['instance_of', 'not_instance_of'] 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 ### PolymorphicModel meta class
@ -91,6 +96,7 @@ class PolymorphicModelBase(ModelBase):
use correct mro, only use managers with _inherited==False (they are of no use), 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) skip managers that are overwritten by the user with same-named class attributes (in attrs)
""" """
#print "** ", self.__name__
add_managers = [] add_managers = []
add_managers_keys = set() add_managers_keys = set()
for base in self.__mro__[1:]: for base in self.__mro__[1:]:
@ -102,9 +108,23 @@ class PolymorphicModelBase(ModelBase):
for key, manager in base.__dict__.items(): for key, manager in base.__dict__.items():
if type(manager) == models.manager.ManagerDescriptor: if type(manager) == models.manager.ManagerDescriptor:
manager = manager.manager 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): if not isinstance(manager, models.Manager):
continue continue
if key in ['_base_manager']: if key == '_base_manager':
continue # let Django handle _base_manager continue # let Django handle _base_manager
if key in attrs: if key in attrs:
continue continue
@ -112,7 +132,8 @@ class PolymorphicModelBase(ModelBase):
continue # manager with that name already added, skip continue # manager with that name already added, skip
if manager._inherited: if manager._inherited:
continue # inherited managers (on the bases) have no significance, they are just copies 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 if isinstance(manager, PolymorphicManager): # validate any inherited polymorphic managers
self.validate_model_manager(manager, self.__name__, key) self.validate_model_manager(manager, self.__name__, key)
add_managers.append((base.__name__, key, manager)) add_managers.append((base.__name__, key, manager))
@ -121,16 +142,18 @@ class PolymorphicModelBase(ModelBase):
@classmethod @classmethod
def get_first_user_defined_manager(self): def get_first_user_defined_manager(self):
# See if there is a manager attribute directly stored at this inheritance level.
mgr_list = [] mgr_list = []
for key, val in self.__dict__.items(): for key, val in self.__dict__.items():
item = getattr(self, key) item = getattr(self, key)
if not isinstance(item, models.Manager): continue if not isinstance(item, models.Manager): continue
mgr_list.append((item.creation_counter, key, item)) mgr_list.append((item.creation_counter, key, item))
# if there are user defined managers, use first one as _default_manager # if there are user defined managers, use first one as _default_manager
if mgr_list: if mgr_list:
_, manager_name, manager = sorted(mgr_list)[0] _, 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' #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 manager
return None 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 # some applications want to know the name of the fields that are added to its models
polymorphic_internal_model_fields = ['polymorphic_ctype'] 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() objects = PolymorphicManager()
base_objects = models.Manager() base_objects = models.Manager()