Skip to content

Commit 1deee93

Browse files
authored
Merge pull request #666 from bckohan/issue546
Add playwright test capability, fix autocomplete bug on new form creation on stacked admin inline pages.
2 parents 78208fb + 2fbd9b9 commit 1deee93

File tree

14 files changed

+433
-81
lines changed

14 files changed

+433
-81
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,6 @@ __marimo__/
218218
.DS_Store
219219

220220
.python-version
221+
222+
test1.db
223+
test2.db

conftest.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
def pytest_configure(config):
2+
# stash it somewhere global-ish
3+
from polymorphic import tests
4+
5+
tests.HEADLESS = not config.getoption("--headed")

docs/changelog.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
Changelog
22
=========
33

4-
v4.2.0 (2025-XX-XX)
4+
v4.2.0 (2025-12-01)
55
-------------------
66

7+
* Fixed `Issue with Autocomplete Fields in StackedPolymorphicInline.Child Inline <https://github.com/jazzband/django-polymorphic/issues/546>`_
78
* Support Python 3.14 and Django 6.0, drop support for EOL python 3.9, Django 3.2, 4.0, 4.1 and 5.0.
89
* `Modernized package management with new build, test, docs tooling and improved CI
910
<https://github.com/jazzband/django-polymorphic/issues/651>`_.

justfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ manage *COMMAND:
1616
from django.core import management
1717
sys.path.append(os.getcwd())
1818
os.environ["DJANGO_SETTINGS_MODULE"] = "polymorphic.tests.settings"
19+
os.environ["SQLITE_DATABASES"] = "test1.db,test2.db"
1920
management.execute_from_command_line(sys.argv + "{{ COMMAND }}".split(" "))
2021

2122
# install the uv package manager
@@ -29,10 +30,11 @@ install_uv:
2930
install_uv:
3031
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
3132

32-
# setup the venv and pre-commit hooks
33+
# setup the venv, pre-commit hooks and playwright dependencies
3334
setup python="python":
3435
uv venv -p {{ python }}
3536
@just run pre-commit install
37+
@just run playwright install
3638

3739
# install git pre-commit hooks
3840
install-precommit:

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ dev = [
151151
"pytest>=8.3.4",
152152
"pytest-cov>=5.0.0",
153153
"pytest-django>=4.10.0",
154+
"pytest-playwright>=0.7.2",
154155
"ruff>=0.9.8",
155156
"tomlkit>=0.13.3",
156157
"tox>=4.24.1",

src/polymorphic/static/polymorphic/js/polymorphic_inlines.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,11 @@
140140
if (options.removed) {
141141
options.removed(row);
142142
}
143-
$(document).trigger('formset:removed', [row, options.prefix]);
143+
document.dispatchEvent(new CustomEvent("formset:removed", {
144+
detail: {
145+
formsetName: options.prefix
146+
}
147+
}));
144148
// Update the TOTAL_FORMS form count.
145149
var forms = $("." + options.formCssClass);
146150
$("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length);
@@ -163,7 +167,12 @@
163167
if (options.added) {
164168
options.added(row);
165169
}
166-
$(document).trigger('formset:added', [row, options.prefix]);
170+
row.get(0).dispatchEvent(new CustomEvent("formset:added", {
171+
bubbles: true,
172+
detail: {
173+
formsetName: options.prefix
174+
}
175+
}));
167176
});
168177
}
169178
return this;

src/polymorphic/tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
HEADLESS = True

src/polymorphic/tests/admin.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from django.contrib.admin import register, ModelAdmin
2+
from polymorphic.admin import StackedPolymorphicInline, PolymorphicInlineSupportMixin
3+
from polymorphic.tests.models import PlainA, InlineModelA, InlineModelB, InlineParent
4+
5+
6+
@register(PlainA)
7+
class PlainAAdmin(ModelAdmin):
8+
search_fields = ["field1"]
9+
10+
11+
class InlineModelAChild(StackedPolymorphicInline.Child):
12+
model = InlineModelA
13+
14+
15+
class InlineModelBChild(StackedPolymorphicInline.Child):
16+
model = InlineModelB
17+
autocomplete_fields = ["plain_a"]
18+
19+
20+
class Inline(StackedPolymorphicInline):
21+
model = InlineModelA
22+
child_inlines = (InlineModelAChild, InlineModelBChild)
23+
24+
25+
@register(InlineParent)
26+
class InlineParentAdmin(PolymorphicInlineSupportMixin, ModelAdmin):
27+
inlines = (Inline,)

src/polymorphic/tests/migrations/0001_initial.py

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generated by Django 4.2.23 on 2025-08-25 13:28
1+
# Generated by Django 4.2.26 on 2025-12-01 11:40
22

33
from django.db import migrations, models
44
import django.db.models.deletion
@@ -89,17 +89,6 @@ class Migration(migrations.Migration):
8989
},
9090
bases=(polymorphic.showfields.ShowFieldType, models.Model),
9191
),
92-
migrations.CreateModel(
93-
name='InlineModelA',
94-
fields=[
95-
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
96-
('field1', models.CharField(max_length=30)),
97-
],
98-
options={
99-
'abstract': False,
100-
'base_manager_name': 'objects',
101-
},
102-
),
10392
migrations.CreateModel(
10493
name='InlineParent',
10594
fields=[
@@ -352,18 +341,6 @@ class Migration(migrations.Migration):
352341
},
353342
bases=('tests.inittestmodel',),
354343
),
355-
migrations.CreateModel(
356-
name='InlineModelB',
357-
fields=[
358-
('inlinemodela_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='tests.inlinemodela')),
359-
('field2', models.CharField(max_length=30)),
360-
],
361-
options={
362-
'abstract': False,
363-
'base_manager_name': 'objects',
364-
},
365-
bases=('tests.inlinemodela',),
366-
),
367344
migrations.CreateModel(
368345
name='Middle',
369346
fields=[
@@ -820,15 +797,18 @@ class Migration(migrations.Migration):
820797
},
821798
bases=(polymorphic.showfields.ShowFieldType, models.Model),
822799
),
823-
migrations.AddField(
824-
model_name='inlinemodela',
825-
name='parent',
826-
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='inline_children', to='tests.inlineparent'),
827-
),
828-
migrations.AddField(
829-
model_name='inlinemodela',
830-
name='polymorphic_ctype',
831-
field=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'),
800+
migrations.CreateModel(
801+
name='InlineModelA',
802+
fields=[
803+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
804+
('field1', models.CharField(max_length=30)),
805+
('parent', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='inline_children', to='tests.inlineparent')),
806+
('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')),
807+
],
808+
options={
809+
'abstract': False,
810+
'base_manager_name': 'objects',
811+
},
832812
),
833813
migrations.CreateModel(
834814
name='Duck',
@@ -1070,6 +1050,19 @@ class Migration(migrations.Migration):
10701050
],
10711051
bases=('tests.uuidplainb',),
10721052
),
1053+
migrations.CreateModel(
1054+
name='InlineModelB',
1055+
fields=[
1056+
('inlinemodela_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='tests.inlinemodela')),
1057+
('field2', models.CharField(max_length=30)),
1058+
('plain_a', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='tests.plaina')),
1059+
],
1060+
options={
1061+
'abstract': False,
1062+
'base_manager_name': 'objects',
1063+
},
1064+
bases=('tests.inlinemodela',),
1065+
),
10731066
migrations.CreateModel(
10741067
name='BlogEntry',
10751068
fields=[

src/polymorphic/tests/models.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
class PlainA(models.Model):
1616
field1 = models.CharField(max_length=30)
1717

18+
def __str__(self):
19+
return self.field1
20+
1821

1922
class PlainB(PlainA):
2023
field2 = models.CharField(max_length=30)
@@ -448,6 +451,10 @@ class InlineModelA(PolymorphicModel):
448451
class InlineModelB(InlineModelA):
449452
field2 = models.CharField(max_length=30)
450453

454+
plain_a = models.ForeignKey(
455+
PlainA, null=True, blank=True, default=None, on_delete=models.SET_NULL
456+
)
457+
451458

452459
class AbstractProject(PolymorphicModel):
453460
topic = models.CharField(max_length=30)

0 commit comments

Comments
 (0)