#37: Fix model subclass ___ selector for abstract/proxy models

fix_request_path_info
Lukasz Zdun 2018-09-29 07:54:15 +02:00
parent 6d27bb3334
commit 14b31bed4c
5 changed files with 122 additions and 8 deletions

1
.gitignore vendored
View File

@ -16,3 +16,4 @@ build/
dist/
docs/_build/
htmlcov/
venv/

View File

@ -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 ''

View File

@ -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',),
),
]

View File

@ -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')

View File

@ -4,7 +4,7 @@ import uuid
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.db.models import Case, Count, Q, When
from django.test import TestCase, TransactionTestCase
from django.test import TransactionTestCase
from django.utils import six
from polymorphic import query_translate
@ -68,13 +68,16 @@ from polymorphic.tests.models import (
ProxyModelA,
ProxyModelB,
ProxyModelBase,
QuerySet,
RedheadDuck,
RelationA,
RelationB,
RelationBC,
RelationBase,
RubberDuck,
SubclassSelectorAbstractBaseModel,
SubclassSelectorAbstractConcreteModel,
SubclassSelectorProxyBaseModel,
SubclassSelectorProxyConcreteModel,
TestParentLinkAndRelatedName,
UUIDArtProject,
UUIDPlainA,
@ -852,21 +855,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)
@ -1006,3 +1009,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)