Fixed #34025 -- Fixed selecting ModelAdmin.autocomplete_fields after adding/changing related instances via popups.

Regression in c72f6f36c1.

Thanks Alexandre da Silva for the report.
This commit is contained in:
David Sanders 2022-09-21 22:56:22 +10:00 committed by Mariusz Felisiak
parent 6e891a1722
commit 9976f3d4b8
4 changed files with 56 additions and 24 deletions

View File

@ -96,7 +96,8 @@
// Extract the model from the popup url '.../<model>/add/' or // Extract the model from the popup url '.../<model>/add/' or
// '.../<model>/<id>/change/' depending the action (add or change). // '.../<model>/<id>/change/' depending the action (add or change).
const modelName = path.split('/')[path.split('/').length - (objId ? 4 : 3)]; const modelName = path.split('/')[path.split('/').length - (objId ? 4 : 3)];
const selectsRelated = document.querySelectorAll(`[data-model-ref="${modelName}"] select`); // Exclude autocomplete selects.
const selectsRelated = document.querySelectorAll(`[data-model-ref="${modelName}"] select:not(.admin-autocomplete)`);
selectsRelated.forEach(function(select) { selectsRelated.forEach(function(select) {
if (currentSelect === select) { if (currentSelect === select) {

View File

@ -23,3 +23,7 @@ Bugfixes
* Fixed a regression in Django 4.1 that caused a * Fixed a regression in Django 4.1 that caused a
``QuerySet.values()/values_list()`` crash on ``ArrayAgg()`` and ``QuerySet.values()/values_list()`` crash on ``ArrayAgg()`` and
``JSONBAgg()`` (:ticket:`34016`). ``JSONBAgg()`` (:ticket:`34016`).
* Fixed a bug in Django 4.1 that caused :attr:`.ModelAdmin.autocomplete_fields`
to be incorrectly selected after adding/changing related instances via popups
(:ticket:`34025`).

View File

@ -1165,6 +1165,14 @@ class GetFormsetsArgumentCheckingAdmin(admin.ModelAdmin):
return super().get_formsets_with_inlines(request, obj) return super().get_formsets_with_inlines(request, obj)
class CountryAdmin(admin.ModelAdmin):
search_fields = ["name"]
class TravelerAdmin(admin.ModelAdmin):
autocomplete_fields = ["living_country"]
site = admin.AdminSite(name="admin") site = admin.AdminSite(name="admin")
site.site_url = "/my-site-url/" site.site_url = "/my-site-url/"
site.register(Article, ArticleAdmin) site.register(Article, ArticleAdmin)
@ -1286,8 +1294,8 @@ site.register(ExplicitlyProvidedPK, GetFormsetsArgumentCheckingAdmin)
site.register(ImplicitlyGeneratedPK, GetFormsetsArgumentCheckingAdmin) site.register(ImplicitlyGeneratedPK, GetFormsetsArgumentCheckingAdmin)
site.register(UserProxy) site.register(UserProxy)
site.register(Box) site.register(Box)
site.register(Country) site.register(Country, CountryAdmin)
site.register(Traveler) site.register(Traveler, TravelerAdmin)
# Register core models we need in our tests # Register core models we need in our tests
site.register(User, UserAdmin) site.register(User, UserAdmin)

View File

@ -6317,18 +6317,24 @@ class SeleniumTests(AdminSeleniumTestCase):
finally: finally:
self.selenium.set_window_size(current_size["width"], current_size["height"]) self.selenium.set_window_size(current_size["width"], current_size["height"])
def test_updating_related_objects_updates_fk_selects(self): def test_updating_related_objects_updates_fk_selects_except_autocompletes(self):
from selenium.webdriver.common.by import By from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select from selenium.webdriver.support.ui import Select
born_country_select_id = "id_born_country" born_country_select_id = "id_born_country"
living_country_select_id = "id_living_country" living_country_select_id = "id_living_country"
living_country_select2_textbox_id = "select2-id_living_country-container"
favorite_country_to_vacation_select_id = "id_favorite_country_to_vacation" favorite_country_to_vacation_select_id = "id_favorite_country_to_vacation"
continent_select_id = "id_continent" continent_select_id = "id_continent"
def _get_HTML_inside_element_by_id(id_): def _get_HTML_inside_element_by_id(id_):
return self.selenium.find_element(By.ID, id_).get_attribute("innerHTML") return self.selenium.find_element(By.ID, id_).get_attribute("innerHTML")
def _get_text_inside_element_by_selector(selector):
return self.selenium.find_element(By.CSS_SELECTOR, selector).get_attribute(
"innerText"
)
self.admin_login( self.admin_login(
username="super", password="secret", login_url=reverse("admin:index") username="super", password="secret", login_url=reverse("admin:index")
) )
@ -6353,12 +6359,16 @@ class SeleniumTests(AdminSeleniumTestCase):
<option value="1" selected="">Argentina</option> <option value="1" selected="">Argentina</option>
""", """,
) )
self.assertHTMLEqual( # Argentina isn't added to the living_country select nor selected by
_get_HTML_inside_element_by_id(living_country_select_id), # the select2 widget.
""" self.assertEqual(
<option value="" selected="">---------</option> _get_text_inside_element_by_selector(f"#{living_country_select_id}"), ""
<option value="1">Argentina</option> )
""", self.assertEqual(
_get_text_inside_element_by_selector(
f"#{living_country_select2_textbox_id}"
),
"",
) )
# Argentina won't appear because favorite_country_to_vacation field has # Argentina won't appear because favorite_country_to_vacation field has
# limit_choices_to. # limit_choices_to.
@ -6386,13 +6396,18 @@ class SeleniumTests(AdminSeleniumTestCase):
<option value="2">Spain</option> <option value="2">Spain</option>
""", """,
) )
self.assertHTMLEqual(
_get_HTML_inside_element_by_id(living_country_select_id), # Spain is added to the living_country select and it's also selected by
""" # the select2 widget.
<option value="" selected="">---------</option> self.assertEqual(
<option value="1">Argentina</option> _get_text_inside_element_by_selector(f"#{living_country_select_id} option"),
<option value="2" selected="">Spain</option> "Spain",
""", )
self.assertEqual(
_get_text_inside_element_by_selector(
f"#{living_country_select2_textbox_id}"
),
"Spain",
) )
# Spain won't appear because favorite_country_to_vacation field has # Spain won't appear because favorite_country_to_vacation field has
# limit_choices_to. # limit_choices_to.
@ -6422,13 +6437,17 @@ class SeleniumTests(AdminSeleniumTestCase):
<option value="2">Italy</option> <option value="2">Italy</option>
""", """,
) )
self.assertHTMLEqual( # Italy is added to the living_country select and it's also selected by
_get_HTML_inside_element_by_id(living_country_select_id), # the select2 widget.
""" self.assertEqual(
<option value="" selected="">---------</option> _get_text_inside_element_by_selector(f"#{living_country_select_id} option"),
<option value="1">Argentina</option> "Italy",
<option value="2" selected="">Italy</option> )
""", self.assertEqual(
_get_text_inside_element_by_selector(
f"#{living_country_select2_textbox_id}"
),
"Italy",
) )
# favorite_country_to_vacation field has no options. # favorite_country_to_vacation field has no options.
self.assertHTMLEqual( self.assertHTMLEqual(