Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion src/polymorphic/tests/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 4.2.26 on 2025-12-01 11:40
# Generated by Django 4.2.26 on 2025-12-02 16:47

from django.db import migrations, models
import django.db.models.deletion
Expand Down Expand Up @@ -197,6 +197,17 @@ class Migration(migrations.Migration):
'base_manager_name': 'objects',
},
),
migrations.CreateModel(
name='Participant',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
),
migrations.CreateModel(
name='PlainA',
fields=[
Expand Down Expand Up @@ -591,6 +602,18 @@ class Migration(migrations.Migration):
},
bases=('tests.modelshow1_plain',),
),
migrations.CreateModel(
name='UserProfile',
fields=[
('participant_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='tests.participant')),
('name', models.CharField(max_length=100)),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('tests.participant',),
),
migrations.CreateModel(
name='UUIDArtProject',
fields=[
Expand Down Expand Up @@ -1050,6 +1073,14 @@ class Migration(migrations.Migration):
],
bases=('tests.uuidplainb',),
),
migrations.CreateModel(
name='Team',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('team_name', models.CharField(max_length=100)),
('user_profiles', models.ManyToManyField(related_name='user_teams', to='tests.userprofile')),
],
),
migrations.CreateModel(
name='InlineModelB',
fields=[
Expand Down
16 changes: 16 additions & 0 deletions src/polymorphic/tests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,3 +519,19 @@ class SubclassSelectorProxyConcreteModel(SubclassSelectorProxyModel):

class NonPolymorphicParent(PolymorphicModel, Group):
test = models.CharField(max_length=30, default="test_non_polymorphic_parent")


class Participant(PolymorphicModel):
pass


class UserProfile(Participant):
name = models.CharField(max_length=100)

def __str__(self):
return self.name


class Team(models.Model):
team_name = models.CharField(max_length=100)
user_profiles = models.ManyToManyField(UserProfile, related_name="user_teams")
40 changes: 39 additions & 1 deletion src/polymorphic/tests/test_regression.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.test import TestCase

from polymorphic.tests.models import Bottom, Middle, Top
from polymorphic.tests.models import Bottom, Middle, Top, Team, UserProfile


class RegressionTests(TestCase):
Expand Down Expand Up @@ -34,3 +34,41 @@ def test_for_query_result_incomplete_with_inheritance(self):
[repr(r) for r in expected_queryset],
transform=repr,
)

def test_pr_254(self):
user_a = UserProfile.objects.create(name="a")
user_b = UserProfile.objects.create(name="b")
user_c = UserProfile.objects.create(name="c")

team1 = Team.objects.create(team_name="team1")
team1.user_profiles.add(user_a, user_b, user_c)
team1.save()

team2 = Team.objects.create(team_name="team2")
team2.user_profiles.add(user_c)
team2.save()

# without prefetch_related, the test passes
my_teams = (
Team.objects.filter(user_profiles=user_c)
.order_by("team_name")
.prefetch_related("user_profiles")
.distinct()
)

self.assertEqual(len(my_teams[0].user_profiles.all()), 3)

self.assertEqual(len(my_teams[1].user_profiles.all()), 1)

self.assertEqual(len(my_teams[0].user_profiles.all()), 3)
self.assertEqual(len(my_teams[1].user_profiles.all()), 1)

# without this "for" loop, the test passes
for _ in my_teams:
pass

# This time, test fails. PR 254 claim
# with sqlite: 4 != 3
# with postgresql: 2 != 3
self.assertEqual(len(my_teams[0].user_profiles.all()), 3)
self.assertEqual(len(my_teams[1].user_profiles.all()), 1)
Loading