[Django] #33111: Conditionally changing ModelAdmin inlines based on object's field breaks saving object in admin site when new inlines should appear

24 views
Skip to first unread message

Django

unread,
Sep 15, 2021, 8:55:06 AM9/15/21
to django-...@googlegroups.com
#33111: Conditionally changing ModelAdmin inlines based on object's field breaks
saving object in admin site when new inlines should appear
-----------------------------------------+------------------------
Reporter: joeli | Owner: nobody
Type: Bug | Status: new
Component: contrib.admin | Version: 3.2
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-----------------------------------------+------------------------
Minimal example:

{{{
#!python

# models.py
class Parent(models.Model):
show_inlines = models.BooleanField(default=False)

class Child(models.Model):
parent = models.ForeignKey(Parent, on_delete=models.CASCADE)


# admin.py
class ChildInline(admin.StackedInline):
model = Child

@admin.register(Parent)
class ParentAdmin(admin.ModelAdmin):
def get_inlines(self, request, obj):
if obj is not None and obj.show_inlines:
return [ChildInline]
return []
}}}

- Create `Parent` objects in either initial state and it works as you'd
expect, where `ChildInline` is rendered when `show_inlines` is True.
- When `show_inlines` is True, you can also set it to False from the admin
site, and the `ChildInline` disappears as expected.
- But when `show_inlines` is False, you cannot re-enable it. Saving the
object fails due to a validation error in the new `ChildInline` that
didn't exist before saving:

{{{
(Hidden field TOTAL_FORMS) This field is required.
(Hidden field INITIAL_FORMS) This field is required.
ManagementForm data is missing or has been tampered with. Missing fields:
child_set-TOTAL_FORMS, child_set-INITIAL_FORMS. You may need to file a bug
report if the issue persists.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/33111>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Sep 16, 2021, 1:05:20 AM9/16/21
to django-...@googlegroups.com
#33111: Conditionally changing ModelAdmin inlines based on object's field breaks
when changing object and new inlines should appear.
-------------------------------+------------------------------------

Reporter: joeli | Owner: nobody
Type: Bug | Status: new
Component: contrib.admin | Version: 3.2
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+------------------------------------
Changes (by Mariusz Felisiak):

* cc: Hasan Ramezani, WeizhongTu (added)
* stage: Unreviewed => Accepted


Comment:

Thanks for the report. I was able to fix this issue by passing an old
instance to the `get_inlines()` 🤔:
{{{
diff --git a/django/contrib/admin/options.py
b/django/contrib/admin/options.py
index 1e5fab917e..7b2b893c10 100644
--- a/django/contrib/admin/options.py
+++ b/django/contrib/admin/options.py
@@ -1585,12 +1585,16 @@ class ModelAdmin(BaseModelAdmin):
)
if request.method == 'POST':
form = ModelForm(request.POST, request.FILES, instance=obj)
+ formsets, inline_instances = self._create_formsets(
+ request,
+ form.instance if add else obj,
+ change=not add,
+ )
form_validated = form.is_valid()
if form_validated:
new_object = self.save_form(request, form, change=not
add)
else:
new_object = form.instance
- formsets, inline_instances = self._create_formsets(request,
new_object, change=not add)
if all_valid(formsets) and form_validated:
self.save_model(request, new_object, form, not add)
self.save_related(request, form, formsets, not add)
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/33111#comment:1>

Django

unread,
Sep 16, 2021, 3:44:15 AM9/16/21
to django-...@googlegroups.com
#33111: Conditionally changing ModelAdmin inlines based on object's field breaks
when changing object and new inlines should appear.
-------------------------------+------------------------------------------
Reporter: joeli | Owner: Hasan Ramezani
Type: Bug | Status: assigned
Component: contrib.admin | Version: 3.2

Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+------------------------------------------
Changes (by Hasan Ramezani):

* owner: nobody => Hasan Ramezani
* status: new => assigned


--
Ticket URL: <https://code.djangoproject.com/ticket/33111#comment:2>

Django

unread,
Sep 16, 2021, 4:59:18 AM9/16/21
to django-...@googlegroups.com
#33111: Conditionally changing ModelAdmin inlines based on object's field breaks
when changing object and new inlines should appear.
-------------------------------+------------------------------------------
Reporter: joeli | Owner: Hasan Ramezani
Type: Bug | Status: assigned
Component: contrib.admin | Version: 3.2

Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+------------------------------------------
Changes (by Hasan Ramezani):

* has_patch: 0 => 1


Comment:

[https://github.com/django/django/pull/14861 PR]

--
Ticket URL: <https://code.djangoproject.com/ticket/33111#comment:3>

Django

unread,
Sep 21, 2021, 7:14:25 AM9/21/21
to django-...@googlegroups.com
#33111: Conditionally changing ModelAdmin inlines based on object's field breaks
when changing object and new inlines should appear.
-------------------------------------+-------------------------------------

Reporter: joeli | Owner: Hasan
| Ramezani
Type: Bug | Status: assigned
Component: contrib.admin | Version: 3.2
Severity: Normal | Resolution:
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak):

* stage: Accepted => Ready for checkin


--
Ticket URL: <https://code.djangoproject.com/ticket/33111#comment:4>

Django

unread,
Sep 21, 2021, 7:36:05 AM9/21/21
to django-...@googlegroups.com
#33111: Conditionally changing ModelAdmin inlines based on object's field breaks
when changing object and new inlines should appear.
-------------------------------------+-------------------------------------
Reporter: joeli | Owner: Hasan
| Ramezani
Type: Bug | Status: closed
Component: contrib.admin | Version: 3.2
Severity: Normal | Resolution: fixed

Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak <felisiak.mariusz@…>):

* status: assigned => closed
* resolution: => fixed


Comment:

In [changeset:"2f0f30f973363a59c20f204f9351724fb2ce7327" 2f0f30f]:
{{{
#!CommitTicketReference repository=""
revision="2f0f30f973363a59c20f204f9351724fb2ce7327"
Fixed #33111 -- Fixed passing object to ModelAdmin.get_inlines() when
editing in admin change view.

ModelAdmin.get_inlines() should get an unmutated object when creating
formsets during POST request.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/33111#comment:5>

Django

unread,
Sep 21, 2021, 7:36:20 AM9/21/21
to django-...@googlegroups.com
#33111: Conditionally changing ModelAdmin inlines based on object's field breaks
when changing object and new inlines should appear.
-------------------------------------+-------------------------------------
Reporter: joeli | Owner: Hasan
| Ramezani
Type: Bug | Status: closed
Component: contrib.admin | Version: 3.2

Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Mariusz Felisiak <felisiak.mariusz@…>):

In [changeset:"668b990bf6da5232b16f979f59bb5d9b3af19e45" 668b990b]:
{{{
#!CommitTicketReference repository=""
revision="668b990bf6da5232b16f979f59bb5d9b3af19e45"
[4.0.x] Fixed #33111 -- Fixed passing object to ModelAdmin.get_inlines()


when editing in admin change view.

ModelAdmin.get_inlines() should get an unmutated object when creating
formsets during POST request.

Backport of 2f0f30f973363a59c20f204f9351724fb2ce7327 from main
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/33111#comment:6>

Reply all
Reply to author
Forward
0 new messages