Nested InlinePanel fails to save when creating >=2 items
See original GitHub issueIssue Summary
When adding new objects within nested InlinePanels, the form fields of the grandchild objects are not allocated unique IDs / names, leading to failures in initialising JS and saving.
Steps to Reproduce
- Start a new project with
wagtail start eventdemo
- Edit home/models.py as follows:
from django.db import models from modelcluster.fields import ParentalKey from modelcluster.models import ClusterableModel from wagtail.core.models import Page, Orderable from wagtail.admin.edit_handlers import FieldPanel, InlinePanel class Event(Orderable): venue = ParentalKey('Venue', related_name='events', on_delete=models.CASCADE) name = models.CharField(max_length=255) date = models.DateField() panels = [ FieldPanel('name'), FieldPanel('date'), ] class Venue(ClusterableModel, Orderable): page = ParentalKey('HomePage', related_name='venues', on_delete=models.CASCADE) name = models.CharField(max_length=255) panels = [ FieldPanel('name'), InlinePanel('events', label="Events"), ] class HomePage(Page): content_panels = [ InlinePanel('venues', label="Venues"), ]
./manage.py makemigrations
,./manage.py migrate
,./manage.py createsuperuser
,./manage.py runserver 0:8000
- Log in to admin, edit the homepage and add a venue and two events. Note that the second date field does not provide a date picker.
- Click ‘save draft’. Note that only one of the events has been saved.
- I have confirmed that this issue can be reproduced as described on a fresh Wagtail project: yes
The root cause of both issues is in the mechanism for adding child objects to the form: the HTML fragment to be inserted is stored in the page as a <script type="text/django-form-template">
block, with __prefix__
placeholders that get replaced with the correct index number (by search-and-replace on the HTML string) when a child is added. When InlinePanels are nested, the template block itself contains another template block also using __prefix__
as the placeholder string, so we can’t distinguish between first-level and second-level placeholders:
<script type="text/django-form-template" id="id_venues-EMPTY_FORM_TEMPLATE">
<li data-inline-panel-child id="inline_child_venues-__prefix__">
...
<label for="id_venues-__prefix__-name">Name:</label>
<input type="text" name="venues-__prefix__-name" maxlength="255" id="id_venues-__prefix__-name">
....
<script type="text/django-form-template" id="id_venues-__prefix__-events-EMPTY_FORM_TEMPLATE">
<li data-inline-panel-child id="inline_child_venues-__prefix__-events-__prefix__">
...
<label for="id_venues-__prefix__-events-__prefix__-name">Name:</label>
<input type="text" name="venues-__prefix__-events-__prefix__-name" maxlength="255" id="id_venues-__prefix__-events-__prefix__-name">
...
<label for="id_venues-__prefix__-events-__prefix__-date">Date:</label>
<input type="text" name="venues-__prefix__-events-__prefix__-date" autocomplete="new-date" id="id_venues-__prefix__-events-__prefix__-date">
<script>initDateChooser("id_venues\u002D__prefix__\u002Devents\u002D__prefix__\u002Ddate", {"dayOfWeekStart": 0, "format": "Y-m-d"});<--/script>
...
</li>
<-/script>
</li>
</script>
Technical details
- Python version: 3.6.8
- Django version: 2.2.6
- Wagtail version: Git master (2.8a0)
- Browser version: Chrome 79.0.3945.117
Issue Analytics
- State:
- Created 4 years ago
- Reactions:5
- Comments:8 (1 by maintainers)
Top Results From Across the Web
Nested categories/InlinePanel(s) in wagtail - Stack Overflow
1 Answer 1 · But I think this requires the snippet to be created first. · I tried it this way, but as...
Read more >Creating an interactive event budgeting tool within Wagtail
This tutorial will walk you through a basic set-up of building an interactive event budgeting tool within the Wagtail page editing interface.
Read more >Wagtail Tip #1: How to replace ParentalManyToManyField ...
In this Wagtail tip, I will talk about How to replace `ParentalManyToManyField` using Wagtail InlinePanel.
Read more >9025 (Nested Inline Support in Admin) - Django's bug tracker
If creating a new pull request, include a link to the pull request in the ... on this class to not show more...
Read more >Panel types — Wagtail Documentation 4.1.1 documentation
For a full explanation on the usage of InlinePanel , see Inline Panels and Model Clusters. Collapsing InlinePanels to save space¶. Note that...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I was looking into this and tried parsing only the first
__prefix__
before realizing I was on the wrong track/being stuck and finally almost gave up.expanding_formset.js
Any thoughts on how a working solution could look like?
Orderable
/Delete
issue or do those__prefix__
related IDs have to be in another way meaningful?InlinePanel
nesting does/shouldwagtail
support?The first form of the outermost inline panel seems to work correctly.
The following code is untested and a quick hacky fix for our scenario. I just wanted it to share.
static/js/expanding_formset.js
:+1 on the modifications from @thaxy and @the5thbeatle, though I had to edit it to
.replace(new RegExp(``${pre}\\\\u002D__prefix__``, 'g'), ``${pre}\\u002D${formCount}``)
added after the firstRegExp
line from @thaxy’s script.