From bb223c6f78afb94f4305fca945f54b8603bb0105 Mon Sep 17 00:00:00 2001 From: Shubh1815 Date: Mon, 15 Nov 2021 19:57:11 +0530 Subject: [PATCH] Fixed #28357 -- Fixed ModelAdmin.prepopulated_fields on newly added stacked inline. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks Jakob Köhler for the initial patch. --- .../contrib/admin/static/admin/js/inlines.js | 8 ++++- .../admin/static/admin/js/prepopulate_init.js | 6 +++- tests/admin_views/admin.py | 16 +++++++++- tests/admin_views/tests.py | 30 +++++++++++++++++-- 4 files changed, 55 insertions(+), 5 deletions(-) diff --git a/django/contrib/admin/static/admin/js/inlines.js b/django/contrib/admin/static/admin/js/inlines.js index d9a9032c45..101fdc7b68 100644 --- a/django/contrib/admin/static/admin/js/inlines.js +++ b/django/contrib/admin/static/admin/js/inlines.js @@ -296,7 +296,13 @@ dependency_list = input.data('dependency_list') || [], dependencies = []; $.each(dependency_list, function(i, field_name) { - dependencies.push('#' + row.find('.form-row .field-' + field_name).find('input, select, textarea').attr('id')); + // Dependency in a fieldset. + let field_element = row.find('.form-row .field-' + field_name); + // Dependency without a fieldset. + if (!field_element.length) { + field_element = row.find('.form-row.field-' + field_name); + } + dependencies.push('#' + field_element.find('input, select, textarea').attr('id')); }); if (dependencies.length) { input.prepopulate(dependencies, input.attr('maxlength')); diff --git a/django/contrib/admin/static/admin/js/prepopulate_init.js b/django/contrib/admin/static/admin/js/prepopulate_init.js index 72ebdcf5d8..a58841f004 100644 --- a/django/contrib/admin/static/admin/js/prepopulate_init.js +++ b/django/contrib/admin/static/admin/js/prepopulate_init.js @@ -3,7 +3,11 @@ const $ = django.jQuery; const fields = $('#django-admin-prepopulated-fields-constants').data('prepopulatedFields'); $.each(fields, function(index, field) { - $('.empty-form .form-row .field-' + field.name + ', .empty-form.form-row .field-' + field.name).addClass('prepopulated_field'); + $( + '.empty-form .form-row .field-' + field.name + + ', .empty-form.form-row .field-' + field.name + + ', .empty-form .form-row.field-' + field.name + ).addClass('prepopulated_field'); $(field.id).data('dependency_list', field.dependency_list).prepopulate( field.dependency_ids, field.maxLength, field.allowUnicode ); diff --git a/tests/admin_views/admin.py b/tests/admin_views/admin.py index 9238c7fabf..3d276b2235 100644 --- a/tests/admin_views/admin.py +++ b/tests/admin_views/admin.py @@ -767,8 +767,22 @@ class RelatedPrepopulatedInline3(admin.TabularInline): autocomplete_fields = ['fk', 'm2m'] +class RelatedPrepopulatedStackedInlineNoFieldsets(admin.StackedInline): + model = RelatedPrepopulated + extra = 1 + prepopulated_fields = { + 'slug1': ['name', 'pubdate'], + 'slug2': ['status'], + } + + class MainPrepopulatedAdmin(admin.ModelAdmin): - inlines = [RelatedPrepopulatedInline1, RelatedPrepopulatedInline2, RelatedPrepopulatedInline3] + inlines = [ + RelatedPrepopulatedInline1, + RelatedPrepopulatedInline2, + RelatedPrepopulatedInline3, + RelatedPrepopulatedStackedInlineNoFieldsets, + ] fieldsets = ( (None, { 'fields': (('pubdate', 'status'), ('name', 'slug1', 'slug2', 'slug3')) diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index 45808b72a7..560d0e6134 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -4611,7 +4611,7 @@ class SeleniumTests(AdminSeleniumTestCase): self.assertEqual(slug2, 'option-two-the-main-name-and-its-awesomeiiii') self.assertEqual(slug3, 'the-main-n\xe0m\xeb-and-its-aw\u03b5\u0161ome\u0131\u0131\u0131i') - # Stacked inlines ---------------------------------------------------- + # Stacked inlines with fieldsets ------------------------------------- # Initial inline self.selenium.find_element(By.ID, 'id_relatedprepopulated_set-0-pubdate').send_keys('2011-12-17') self.select_option('#id_relatedprepopulated_set-0-status', 'option one') @@ -4687,6 +4687,32 @@ class SeleniumTests(AdminSeleniumTestCase): len(self.selenium.find_elements(By.CLASS_NAME, 'select2-selection')), num_initial_select2_inputs + 6 ) + # Stacked Inlines without fieldsets ---------------------------------- + # Initial inline. + row_id = 'id_relatedprepopulated_set-4-0-' + self.selenium.find_element(By.ID, f'{row_id}pubdate').send_keys('2011-12-12') + self.select_option(f'#{row_id}status', 'option one') + self.selenium.find_element(By.ID, f'{row_id}name').send_keys(' sŤāÇkeð inline ! ') + slug1 = self.selenium.find_element(By.ID, f'{row_id}slug1').get_attribute('value') + slug2 = self.selenium.find_element(By.ID, f'{row_id}slug2').get_attribute('value') + self.assertEqual(slug1, 'stacked-inline-2011-12-12') + self.assertEqual(slug2, 'option-one') + # Add inline. + self.selenium.find_elements( + By.LINK_TEXT, + 'Add another Related prepopulated', + )[3].click() + row_id = 'id_relatedprepopulated_set-4-1-' + self.selenium.find_element(By.ID, f'{row_id}pubdate').send_keys('1999-01-20') + self.select_option(f'#{row_id}status', 'option two') + self.selenium.find_element(By.ID, f'{row_id}name').send_keys( + ' now you haVe anöther sŤāÇkeð inline with a very loooong ' + ) + slug1 = self.selenium.find_element(By.ID, f'{row_id}slug1').get_attribute('value') + slug2 = self.selenium.find_element(By.ID, f'{row_id}slug2').get_attribute('value') + self.assertEqual(slug1, 'now-you-have-another-stacked-inline-with-a-very-lo') + self.assertEqual(slug2, 'option-two') + # Save and check that everything is properly stored in the database with self.wait_page_loaded(): self.selenium.find_element(By.XPATH, '//input[@value="Save"]').click() @@ -4699,7 +4725,7 @@ class SeleniumTests(AdminSeleniumTestCase): slug2='option-two-the-main-name-and-its-awesomeiiii', slug3='the-main-nàmë-and-its-awεšomeıııi', ) - self.assertEqual(RelatedPrepopulated.objects.all().count(), 4) + self.assertEqual(RelatedPrepopulated.objects.all().count(), 6) RelatedPrepopulated.objects.get( name=' here is a sŤāÇkeð inline ! ', pubdate='2011-12-17',