make sure 'base_manager is not inherited (but managed by Django instead).
(This seems more correct but it doen't seem to make any difference.) Also added related test cases.fix_request_path_info
parent
6628145af7
commit
b2357592cb
|
|
@ -213,7 +213,6 @@ ul.auto-toc {
|
||||||
|
|
||||||
<div class="section" id="polymorphic-models-for-django">
|
<div class="section" id="polymorphic-models-for-django">
|
||||||
<h1>Polymorphic Models for Django</h1>
|
<h1>Polymorphic Models for Django</h1>
|
||||||
<p>.</p>
|
|
||||||
<div class="section" id="quick-start-docs-contributing">
|
<div class="section" id="quick-start-docs-contributing">
|
||||||
<h2>Quick Start, Docs, Contributing</h2>
|
<h2>Quick Start, Docs, Contributing</h2>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
Polymorphic Models for Django
|
Polymorphic Models for Django
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
.
|
|
||||||
|
|
||||||
Quick Start, Docs, Contributing
|
Quick Start, Docs, Contributing
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
|
||||||
|
|
@ -92,9 +92,11 @@ class PolymorphicModelBase(ModelBase):
|
||||||
for key, manager in base.__dict__.items():
|
for key, manager in base.__dict__.items():
|
||||||
if type(manager) == models.manager.ManagerDescriptor: manager = manager.manager
|
if type(manager) == models.manager.ManagerDescriptor: manager = manager.manager
|
||||||
if not isinstance(manager, models.Manager): continue
|
if not isinstance(manager, models.Manager): continue
|
||||||
|
if key in ['_base_manager']: continue # let Django handle _base_manager
|
||||||
if key in attrs: continue
|
if key in attrs: continue
|
||||||
if key in add_managers_keys: continue # manager with that name already added, skip
|
if key in add_managers_keys: continue # manager with that name already added, skip
|
||||||
if manager._inherited: continue # inherited managers have no significance, they are just copies
|
if manager._inherited: continue # inherited managers (on the bases) have no significance, they are just copies
|
||||||
|
#print >>sys.stderr,'##',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))
|
||||||
|
|
|
||||||
|
|
@ -135,25 +135,24 @@ class PolymorphicModel(models.Model):
|
||||||
our appropriate base_objects manager.
|
our appropriate base_objects manager.
|
||||||
"""
|
"""
|
||||||
super(PolymorphicModel, self).__init__(*args, ** kwargs)
|
super(PolymorphicModel, self).__init__(*args, ** kwargs)
|
||||||
|
|
||||||
if self.__class__.polymorphic_super_sub_accessors_replaced: return
|
if self.__class__.polymorphic_super_sub_accessors_replaced: return
|
||||||
self.__class__.polymorphic_super_sub_accessors_replaced = True
|
self.__class__.polymorphic_super_sub_accessors_replaced = True
|
||||||
|
|
||||||
def create_accessor_function_for_model(model):
|
def create_accessor_function_for_model(model, accessor_name):
|
||||||
def accessor_function(self):
|
def accessor_function(self):
|
||||||
attr = model.base_objects.get(pk=self.pk)
|
attr = model.base_objects.get(pk=self.pk)
|
||||||
return attr
|
return attr
|
||||||
return accessor_function
|
return accessor_function
|
||||||
|
|
||||||
subclasses_and_superclasses_accessors = self.get_inheritance_relation_fields_and_models()
|
subclasses_and_superclasses_accessors = self.get_inheritance_relation_fields_and_models()
|
||||||
#print '###',self.__class__.__name__,subclasses_and_superclasses_accessors
|
|
||||||
|
|
||||||
from django.db.models.fields.related import SingleRelatedObjectDescriptor, ReverseSingleRelatedObjectDescriptor
|
from django.db.models.fields.related import SingleRelatedObjectDescriptor, ReverseSingleRelatedObjectDescriptor
|
||||||
|
|
||||||
for name,model in subclasses_and_superclasses_accessors.iteritems():
|
for name,model in subclasses_and_superclasses_accessors.iteritems():
|
||||||
orig_accessor = getattr(self.__class__, name, None)
|
orig_accessor = getattr(self.__class__, name, None)
|
||||||
if type(orig_accessor) in [SingleRelatedObjectDescriptor,ReverseSingleRelatedObjectDescriptor]:
|
if type(orig_accessor) in [SingleRelatedObjectDescriptor,ReverseSingleRelatedObjectDescriptor]:
|
||||||
#print 'replacing',name, orig_accessor
|
#print >>sys.stderr, '---------- replacing',name, orig_accessor
|
||||||
setattr(self.__class__, name, property(create_accessor_function_for_model(model)) )
|
setattr(self.__class__, name, property(create_accessor_function_for_model(model, name)) )
|
||||||
|
|
||||||
def get_inheritance_relation_fields_and_models(self):
|
def get_inheritance_relation_fields_and_models(self):
|
||||||
"""helper function for __init__:
|
"""helper function for __init__:
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import settings
|
import settings
|
||||||
|
import sys
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.db.models.query import QuerySet
|
from django.db.models.query import QuerySet
|
||||||
|
|
@ -29,6 +30,8 @@ class Model2B(Model2A):
|
||||||
field2 = models.CharField(max_length=10)
|
field2 = models.CharField(max_length=10)
|
||||||
class Model2C(Model2B):
|
class Model2C(Model2B):
|
||||||
field3 = models.CharField(max_length=10)
|
field3 = models.CharField(max_length=10)
|
||||||
|
class Model2D(Model2C):
|
||||||
|
field4 = models.CharField(max_length=10)
|
||||||
|
|
||||||
class ModelShow1(ShowFieldType,PolymorphicModel):
|
class ModelShow1(ShowFieldType,PolymorphicModel):
|
||||||
field1 = models.CharField(max_length=10)
|
field1 = models.CharField(max_length=10)
|
||||||
|
|
@ -84,6 +87,13 @@ class RelationBC(RelationB):
|
||||||
class RelatingModel(models.Model):
|
class RelatingModel(models.Model):
|
||||||
many2many = models.ManyToManyField(Model2A)
|
many2many = models.ManyToManyField(Model2A)
|
||||||
|
|
||||||
|
class One2OneRelatingModel(PolymorphicModel):
|
||||||
|
one2one = models.OneToOneField(Model2A)
|
||||||
|
field1 = models.CharField(max_length=10)
|
||||||
|
|
||||||
|
class One2OneRelatingModelDerived(One2OneRelatingModel):
|
||||||
|
field2 = models.CharField(max_length=10)
|
||||||
|
|
||||||
class MyManager(PolymorphicManager):
|
class MyManager(PolymorphicManager):
|
||||||
def get_query_set(self):
|
def get_query_set(self):
|
||||||
return super(MyManager, self).get_query_set().order_by('-field1')
|
return super(MyManager, self).get_query_set().order_by('-field1')
|
||||||
|
|
@ -243,25 +253,27 @@ class testclass(TestCase):
|
||||||
entry2 = BlogEntry_limit_choices_to.objects.create(blog=blog_b, text='bla2')
|
entry2 = BlogEntry_limit_choices_to.objects.create(blog=blog_b, text='bla2')
|
||||||
|
|
||||||
|
|
||||||
|
def show_base_manager(model):
|
||||||
|
print type(model._base_manager),model._base_manager.model
|
||||||
|
|
||||||
__test__ = {"doctest": """
|
__test__ = {"doctest": """
|
||||||
#######################################################
|
#######################################################
|
||||||
### Tests
|
### Tests
|
||||||
|
|
||||||
>>> settings.DEBUG=True
|
>>> settings.DEBUG=True
|
||||||
|
|
||||||
#>>> get_version()
|
|
||||||
#'1.0 rc1'
|
|
||||||
|
|
||||||
|
|
||||||
### simple inheritance
|
### simple inheritance
|
||||||
|
|
||||||
>>> o=Model2A.objects.create(field1='A1')
|
>>> o=Model2A.objects.create(field1='A1')
|
||||||
>>> o=Model2B.objects.create(field1='B1', field2='B2')
|
>>> o=Model2B.objects.create(field1='B1', field2='B2')
|
||||||
>>> o=Model2C.objects.create(field1='C1', field2='C2', field3='C3')
|
>>> o=Model2C.objects.create(field1='C1', field2='C2', field3='C3')
|
||||||
|
>>> o=Model2D.objects.create(field1='D1', field2='D2', field3='D3', field4='D4')
|
||||||
[ <Model2A: id 1, field1 (CharField)>,
|
>>> Model2A.objects.all()
|
||||||
|
[ <Model2A: id 1, field1 (CharField)>,
|
||||||
<Model2B: id 2, field1 (CharField), field2 (CharField)>,
|
<Model2B: id 2, field1 (CharField), field2 (CharField)>,
|
||||||
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)> ]
|
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>,
|
||||||
|
<Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)> ]
|
||||||
|
|
||||||
# manual get_real_instance()
|
# manual get_real_instance()
|
||||||
>>> o=Model2A.base_objects.get(field1='C1')
|
>>> o=Model2A.base_objects.get(field1='C1')
|
||||||
|
|
@ -269,6 +281,48 @@ __test__ = {"doctest": """
|
||||||
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>
|
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>
|
||||||
|
|
||||||
|
|
||||||
|
### test inheritance pointers & _base_managers
|
||||||
|
|
||||||
|
>>> show_base_manager(PlainA)
|
||||||
|
<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.PlainA'>
|
||||||
|
>>> show_base_manager(PlainB)
|
||||||
|
<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.PlainB'>
|
||||||
|
>>> show_base_manager(PlainC)
|
||||||
|
<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.PlainC'>
|
||||||
|
>>> show_base_manager(Model2A)
|
||||||
|
<class 'polymorphic.manager.PolymorphicManager'> <class 'polymorphic.tests.Model2A'>
|
||||||
|
>>> show_base_manager(Model2B)
|
||||||
|
<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.Model2B'>
|
||||||
|
>>> show_base_manager(Model2C)
|
||||||
|
<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.Model2C'>
|
||||||
|
>>> show_base_manager(One2OneRelatingModel)
|
||||||
|
<class 'polymorphic.manager.PolymorphicManager'> <class 'polymorphic.tests.One2OneRelatingModel'>
|
||||||
|
>>> show_base_manager(One2OneRelatingModelDerived)
|
||||||
|
<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.One2OneRelatingModelDerived'>
|
||||||
|
|
||||||
|
>>> o=Model2A.base_objects.get(field1='C1')
|
||||||
|
>>> o.model2b
|
||||||
|
<Model2B: id 3, field1 (CharField), field2 (CharField)>
|
||||||
|
|
||||||
|
>>> o=Model2B.base_objects.get(field1='C1')
|
||||||
|
>>> o.model2c
|
||||||
|
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>
|
||||||
|
|
||||||
|
|
||||||
|
### OneToOneField, test both directions for polymorphism
|
||||||
|
|
||||||
|
>>> a=Model2A.base_objects.get(field1='C1')
|
||||||
|
>>> b=One2OneRelatingModelDerived.objects.create(one2one=a, field1='f1', field2='f2')
|
||||||
|
>>> b.one2one # this result is basically wrong, probably due to Django cacheing (we used base_objects), but should not be a problem
|
||||||
|
<Model2A: id 3, field1 (CharField)>
|
||||||
|
>>> c=One2OneRelatingModelDerived.objects.get(field1='f1')
|
||||||
|
>>> c.one2one
|
||||||
|
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>
|
||||||
|
|
||||||
|
>>> a.one2onerelatingmodel
|
||||||
|
<One2OneRelatingModelDerived: One2OneRelatingModelDerived object>
|
||||||
|
|
||||||
|
|
||||||
### ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent, also with annotate()
|
### ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent, also with annotate()
|
||||||
|
|
||||||
>>> o=ModelShow1.objects.create(field1='abc')
|
>>> o=ModelShow1.objects.create(field1='abc')
|
||||||
|
|
@ -315,15 +369,18 @@ __test__ = {"doctest": """
|
||||||
|
|
||||||
>>> Model2A.objects.instance_of(Model2B)
|
>>> Model2A.objects.instance_of(Model2B)
|
||||||
[ <Model2B: id 2, field1 (CharField), field2 (CharField)>,
|
[ <Model2B: id 2, field1 (CharField), field2 (CharField)>,
|
||||||
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)> ]
|
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>,
|
||||||
|
<Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)> ]
|
||||||
|
|
||||||
>>> Model2A.objects.filter(instance_of=Model2B)
|
>>> Model2A.objects.filter(instance_of=Model2B)
|
||||||
[ <Model2B: id 2, field1 (CharField), field2 (CharField)>,
|
[ <Model2B: id 2, field1 (CharField), field2 (CharField)>,
|
||||||
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)> ]
|
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>,
|
||||||
|
<Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)> ]
|
||||||
|
|
||||||
>>> Model2A.objects.filter(Q(instance_of=Model2B))
|
>>> Model2A.objects.filter(Q(instance_of=Model2B))
|
||||||
[ <Model2B: id 2, field1 (CharField), field2 (CharField)>,
|
[ <Model2B: id 2, field1 (CharField), field2 (CharField)>,
|
||||||
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)> ]
|
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>,
|
||||||
|
<Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)> ]
|
||||||
|
|
||||||
>>> Model2A.objects.not_instance_of(Model2B)
|
>>> Model2A.objects.not_instance_of(Model2B)
|
||||||
[ <Model2A: id 1, field1 (CharField)> ]
|
[ <Model2A: id 1, field1 (CharField)> ]
|
||||||
|
|
@ -345,7 +402,8 @@ __test__ = {"doctest": """
|
||||||
>>> oa.delete()
|
>>> oa.delete()
|
||||||
>>> Model2A.objects.all()
|
>>> Model2A.objects.all()
|
||||||
[ <Model2A: id 1, field1 (CharField)>,
|
[ <Model2A: id 1, field1 (CharField)>,
|
||||||
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)> ]
|
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>,
|
||||||
|
<Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)> ]
|
||||||
|
|
||||||
|
|
||||||
### queryset combining
|
### queryset combining
|
||||||
|
|
@ -405,8 +463,8 @@ __test__ = {"doctest": """
|
||||||
>>> o=ModelWithMyManager.objects.create(field1='D1b', field4='D4b')
|
>>> o=ModelWithMyManager.objects.create(field1='D1b', field4='D4b')
|
||||||
|
|
||||||
>>> ModelWithMyManager.objects.all()
|
>>> ModelWithMyManager.objects.all()
|
||||||
[ <ModelWithMyManager: id 5, field1 (CharField): "D1b", field4 (CharField): "D4b">,
|
[ <ModelWithMyManager: id 6, field1 (CharField): "D1b", field4 (CharField): "D4b">,
|
||||||
<ModelWithMyManager: id 4, field1 (CharField): "D1a", field4 (CharField): "D4a"> ]
|
<ModelWithMyManager: id 5, field1 (CharField): "D1a", field4 (CharField): "D4a"> ]
|
||||||
|
|
||||||
>>> type(ModelWithMyManager.objects)
|
>>> type(ModelWithMyManager.objects)
|
||||||
<class 'polymorphic.tests.MyManager'>
|
<class 'polymorphic.tests.MyManager'>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue