Merge pull request #365 from ghost/fix/37-subclass-selector-on-abstract-proxy-models
#37: Fix model subclass ___ selector for abstract/proxy modelsfix_request_path_info
commit
ec3fb34f08
|
|
@ -16,3 +16,4 @@ build/
|
|||
dist/
|
||||
docs/_build/
|
||||
htmlcov/
|
||||
venv/
|
||||
|
|
|
|||
|
|
@ -196,6 +196,8 @@ def translate_polymorphic_field_path(queryset_model, field_path):
|
|||
return myclass.__name__.lower()
|
||||
path = _create_base_path(baseclass, b)
|
||||
if path:
|
||||
if b._meta.abstract or b._meta.proxy:
|
||||
return myclass.__name__.lower()
|
||||
return path + '__' + myclass.__name__.lower()
|
||||
return ''
|
||||
|
||||
|
|
|
|||
|
|
@ -1130,4 +1130,66 @@ class Migration(migrations.Migration):
|
|||
},
|
||||
bases=('tests.duck',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SubclassSelectorAbstractBaseModel',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('base_field', models.CharField(default='test_bf', max_length=10)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SubclassSelectorProxyBaseModel',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('base_field', models.CharField(default='test_bf', max_length=10)),
|
||||
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_tests.subclassselectorproxybasemodel_set+', to='contenttypes.ContentType')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SubclassSelectorAbstractConcreteModel',
|
||||
fields=[
|
||||
('subclassselectorabstractbasemodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='tests.SubclassSelectorAbstractBaseModel')),
|
||||
('abstract_field', models.CharField(default='test_af', max_length=10)),
|
||||
('concrete_field', models.CharField(default='test_cf', max_length=10)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('tests.subclassselectorabstractbasemodel',),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subclassselectorabstractbasemodel',
|
||||
name='polymorphic_ctype',
|
||||
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_tests.subclassselectorabstractbasemodel_set+', to='contenttypes.ContentType'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SubclassSelectorProxyModel',
|
||||
fields=[
|
||||
],
|
||||
options={
|
||||
'proxy': True,
|
||||
'indexes': [],
|
||||
},
|
||||
bases=('tests.subclassselectorproxybasemodel',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SubclassSelectorProxyConcreteModel',
|
||||
fields=[
|
||||
('subclassselectorproxybasemodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='tests.SubclassSelectorProxyBaseModel')),
|
||||
('concrete_field', models.CharField(default='test_cf', max_length=10)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
bases=('tests.subclassselectorproxymodel',),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -450,3 +450,31 @@ class MultiTableBase(PolymorphicModel):
|
|||
|
||||
class MultiTableDerived(MultiTableBase):
|
||||
field2 = models.CharField(max_length=10)
|
||||
|
||||
|
||||
class SubclassSelectorAbstractBaseModel(PolymorphicModel):
|
||||
base_field = models.CharField(max_length=10, default='test_bf')
|
||||
|
||||
|
||||
class SubclassSelectorAbstractModel(SubclassSelectorAbstractBaseModel):
|
||||
abstract_field = models.CharField(max_length=10, default='test_af')
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
||||
class SubclassSelectorAbstractConcreteModel(SubclassSelectorAbstractModel):
|
||||
concrete_field = models.CharField(max_length=10, default='test_cf')
|
||||
|
||||
|
||||
class SubclassSelectorProxyBaseModel(PolymorphicModel):
|
||||
base_field = models.CharField(max_length=10, default='test_bf')
|
||||
|
||||
|
||||
class SubclassSelectorProxyModel(SubclassSelectorProxyBaseModel):
|
||||
class Meta:
|
||||
proxy = True
|
||||
|
||||
|
||||
class SubclassSelectorProxyConcreteModel(SubclassSelectorProxyModel):
|
||||
concrete_field = models.CharField(max_length=10, default='test_cf')
|
||||
|
|
@ -74,6 +74,10 @@ from polymorphic.tests.models import (
|
|||
RelationBC,
|
||||
RelationBase,
|
||||
RubberDuck,
|
||||
SubclassSelectorAbstractBaseModel,
|
||||
SubclassSelectorAbstractConcreteModel,
|
||||
SubclassSelectorProxyBaseModel,
|
||||
SubclassSelectorProxyConcreteModel,
|
||||
TestParentLinkAndRelatedName,
|
||||
UUIDArtProject,
|
||||
UUIDPlainA,
|
||||
|
|
@ -859,21 +863,21 @@ class PolymorphicTests(TransactionTestCase):
|
|||
self.assertEqual(ProxyModelB.objects.model, ProxyModelB)
|
||||
|
||||
# Create objects
|
||||
ProxyModelA.objects.create(name="object1")
|
||||
ProxyModelB.objects.create(name="object2", field2="bb")
|
||||
object1_pk = ProxyModelA.objects.create(name="object1").pk
|
||||
object2_pk = ProxyModelB.objects.create(name="object2", field2="bb").pk
|
||||
|
||||
# Getting single objects
|
||||
object1 = ProxyModelBase.objects.get(name='object1')
|
||||
object2 = ProxyModelBase.objects.get(name='object2')
|
||||
self.assertEqual(repr(object1), '<ProxyModelA: id 1, name (CharField) "object1", field1 (CharField) "">')
|
||||
self.assertEqual(repr(object2), '<ProxyModelB: id 2, name (CharField) "object2", field2 (CharField) "bb">')
|
||||
self.assertEqual(repr(object1), '<ProxyModelA: id %i, name (CharField) "object1", field1 (CharField) "">' % object1_pk)
|
||||
self.assertEqual(repr(object2), '<ProxyModelB: id %i, name (CharField) "object2", field2 (CharField) "bb">' % object2_pk)
|
||||
self.assertIsInstance(object1, ProxyModelA)
|
||||
self.assertIsInstance(object2, ProxyModelB)
|
||||
|
||||
# Same for lists
|
||||
objects = list(ProxyModelBase.objects.all().order_by('name'))
|
||||
self.assertEqual(repr(objects[0]), '<ProxyModelA: id 1, name (CharField) "object1", field1 (CharField) "">')
|
||||
self.assertEqual(repr(objects[1]), '<ProxyModelB: id 2, name (CharField) "object2", field2 (CharField) "bb">')
|
||||
self.assertEqual(repr(objects[0]), '<ProxyModelA: id %i, name (CharField) "object1", field1 (CharField) "">' % object1_pk)
|
||||
self.assertEqual(repr(objects[1]), '<ProxyModelB: id %i, name (CharField) "object2", field2 (CharField) "bb">' % object2_pk)
|
||||
self.assertIsInstance(objects[0], ProxyModelA)
|
||||
self.assertIsInstance(objects[1], ProxyModelB)
|
||||
|
||||
|
|
@ -1024,3 +1028,21 @@ class PolymorphicTests(TransactionTestCase):
|
|||
MultiTableDerived.objects.bulk_create([
|
||||
MultiTableDerived(field1='field1', field2='field2')
|
||||
])
|
||||
|
||||
def test_can_query_using_subclass_selector_on_abstract_model(self):
|
||||
obj = SubclassSelectorAbstractConcreteModel.objects.create(concrete_field='abc')
|
||||
|
||||
queried_obj = SubclassSelectorAbstractBaseModel.objects.filter(
|
||||
SubclassSelectorAbstractConcreteModel___concrete_field='abc'
|
||||
).get()
|
||||
|
||||
self.assertEqual(obj.pk, queried_obj.pk)
|
||||
|
||||
def test_can_query_using_subclass_selector_on_proxy_model(self):
|
||||
obj = SubclassSelectorProxyConcreteModel.objects.create(concrete_field='abc')
|
||||
|
||||
queried_obj = SubclassSelectorProxyBaseModel.objects.filter(
|
||||
SubclassSelectorProxyConcreteModel___concrete_field='abc'
|
||||
).get()
|
||||
|
||||
self.assertEqual(obj.pk, queried_obj.pk)
|
||||
|
|
|
|||
Loading…
Reference in New Issue