Skip to content

Commit 9399f7d

Browse files
authored
Merge pull request #580 from TarunvirBains/parentadmin-behave-as-admin
Show full admin context (breadcrumb and logout nav) in model type selection admin form
2 parents 3d4cacb + 47323bd commit 9399f7d

File tree

4 files changed

+118
-4
lines changed

4 files changed

+118
-4
lines changed

docs/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Changelog
44
v4.2.0 (2025-12-01)
55
-------------------
66

7+
* Fixed `Show full admin context (breadcrumb and logout nav) in model type selection admin form <https://github.com/jazzband/django-polymorphic/pull/580>`_
78
* Fixed `Issue with Autocomplete Fields in StackedPolymorphicInline.Child Inline <https://github.com/jazzband/django-polymorphic/issues/546>`_
89
* 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.
910
* `Modernized package management with new build, test, docs tooling and improved CI

src/polymorphic/admin/parentadmin.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ def render_add_type_form(self, request, context, form_url=""):
345345
"opts": opts,
346346
"add": True,
347347
"save_on_top": self.save_on_top,
348+
**self.admin_site.each_context(request),
348349
}
349350
)
350351

@@ -356,7 +357,7 @@ def render_add_type_form(self, request, context, form_url=""):
356357
]
357358

358359
request.current_app = self.admin_site.name
359-
return TemplateResponse(request, templates, context)
360+
return self.admin_site.admin_view(TemplateResponse)(request, templates, context)
360361

361362
@property
362363
def change_list_template(self):

src/polymorphic/tests/admin.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,33 @@
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
1+
from django.contrib.admin import register, ModelAdmin, site as admin_site
2+
from polymorphic.admin import (
3+
StackedPolymorphicInline,
4+
PolymorphicInlineSupportMixin,
5+
PolymorphicChildModelAdmin,
6+
PolymorphicChildModelFilter,
7+
PolymorphicParentModelAdmin,
8+
)
9+
10+
from polymorphic.tests.models import (
11+
PlainA,
12+
Model2A,
13+
Model2B,
14+
Model2C,
15+
Model2D,
16+
InlineModelA,
17+
InlineModelB,
18+
InlineParent,
19+
)
20+
21+
22+
@register(Model2A)
23+
class Model2Admin(PolymorphicParentModelAdmin):
24+
list_filter = (PolymorphicChildModelFilter,)
25+
child_models = (Model2B, Model2C, Model2D)
26+
27+
28+
admin_site.register(Model2B, PolymorphicChildModelAdmin)
29+
admin_site.register(Model2C, PolymorphicChildModelAdmin)
30+
admin_site.register(Model2D, PolymorphicChildModelAdmin)
431

532

633
@register(PlainA)

src/polymorphic/tests/test_admin.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,3 +278,88 @@ def test_admin_inline_add_autocomplete(self):
278278

279279
suggestions = self.page.locator("ul.select2-results__options > li").all_inner_texts()
280280
assert suggestions == ["Brian"]
281+
282+
283+
class PolymorphicFormTests(_GenericAdminFormTest):
284+
def setUp(self):
285+
Model2A.objects.all().delete()
286+
super().setUp()
287+
288+
def tearDown(self):
289+
Model2A.objects.all().delete()
290+
super().tearDown()
291+
292+
def test_admin_polymorphic_add(self):
293+
model2b_ct = ContentType.objects.get_for_model(Model2B)
294+
model2c_ct = ContentType.objects.get_for_model(Model2C)
295+
model2d_ct = ContentType.objects.get_for_model(Model2D)
296+
297+
for model_type, fields in [
298+
(
299+
model2b_ct,
300+
{
301+
"field1": "2B1",
302+
"field2": "2B2",
303+
},
304+
),
305+
(
306+
model2c_ct,
307+
{
308+
"field1": "2C1",
309+
"field2": "2C2",
310+
"field3": "2C3",
311+
},
312+
),
313+
(
314+
model2d_ct,
315+
{
316+
"field1": "2D1",
317+
"field2": "2D2",
318+
"field3": "2D3",
319+
"field4": "2D4",
320+
},
321+
),
322+
]:
323+
self.page.goto(self.add_url(Model2A))
324+
325+
# https://github.com/jazzband/django-polymorphic/pull/580
326+
expect(self.page.locator("div.breadcrumbs")).to_have_count(1)
327+
expect(self.page.locator("form#logout-form")).to_have_count(1)
328+
329+
self.page.locator(f"input[type=radio][value='{model_type.pk}']").check()
330+
with self.page.expect_navigation(timeout=10000) as nav_info:
331+
self.page.click("input[name='_save']")
332+
333+
response = nav_info.value
334+
assert response.status < 400
335+
336+
for field, value in fields.items():
337+
self.page.fill(f"input[name='{field}']", value)
338+
339+
with self.page.expect_navigation(timeout=10000) as nav_info:
340+
self.page.click("input[name='_save']")
341+
342+
response = nav_info.value
343+
assert response.status < 400
344+
345+
assert Model2A.objects.count() == 3
346+
347+
object_ids = [int(oid) for oid in self.get_object_ids(Model2A)]
348+
349+
assert len(object_ids) == 3
350+
351+
assert Model2B.objects.first().pk in object_ids
352+
assert Model2C.objects.first().pk in object_ids
353+
assert Model2D.objects.first().pk in object_ids
354+
355+
assert Model2B.objects.first().field1 == "2B1"
356+
assert Model2B.objects.first().field2 == "2B2"
357+
358+
assert Model2C.objects.first().field1 == "2C1"
359+
assert Model2C.objects.first().field2 == "2C2"
360+
assert Model2C.objects.first().field3 == "2C3"
361+
362+
assert Model2D.objects.first().field1 == "2D1"
363+
assert Model2D.objects.first().field2 == "2D2"
364+
assert Model2D.objects.first().field3 == "2D3"
365+
assert Model2D.objects.first().field4 == "2D4"

0 commit comments

Comments
 (0)