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

This commit is contained in:
Lukasz Zdun
2018-09-29 07:54:15 +02:00
parent 6d27bb3334
commit 14b31bed4c
5 changed files with 122 additions and 8 deletions
+2
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 ''
@@ -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',),
),
]
+28
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')
+29 -8
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)