summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Sanders <shang.xiao.sanders@gmail.com>2022-09-21 22:56:22 +1000
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-09-28 12:54:48 +0200
commit33d9247c8b8be89518158c19b48a85a8c2d649c5 (patch)
tree638e842681231cb5eadea2a328a8c32704973202
parent4f7fc378a1be02643b909bf013bac17d43b91538 (diff)
[4.1.x] Fixed #34025 -- Fixed selecting ModelAdmin.autocomplete_fields after adding/changing related instances via popups.
Regression in c72f6f36c13a21f6db3d4f85d2d3cec87bad45e6. Thanks Alexandre da Silva for the report. Backport of 9976f3d4b80cfb2e6f4c998438622b78eb1ac53e from main
-rw-r--r--django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js3
-rw-r--r--docs/releases/4.1.2.txt4
-rw-r--r--tests/admin_views/admin.py12
-rw-r--r--tests/admin_views/tests.py61
4 files changed, 56 insertions, 24 deletions
diff --git a/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js b/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js
index 5c9c0d833d..752dcad7bf 100644
--- a/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js
+++ b/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js
@@ -96,7 +96,8 @@
// Extract the model from the popup url '.../<model>/add/' or
// '.../<model>/<id>/change/' depending the action (add or change).
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) {
if (currentSelect === select) {
diff --git a/docs/releases/4.1.2.txt b/docs/releases/4.1.2.txt
index 6a473c16eb..809d583a78 100644
--- a/docs/releases/4.1.2.txt
+++ b/docs/releases/4.1.2.txt
@@ -23,3 +23,7 @@ Bugfixes
* Fixed a regression in Django 4.1 that caused a
``QuerySet.values()/values_list()`` crash on ``ArrayAgg()`` and
``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`).
diff --git a/tests/admin_views/admin.py b/tests/admin_views/admin.py
index 996f7d5afc..9241034ffb 100644
--- a/tests/admin_views/admin.py
+++ b/tests/admin_views/admin.py
@@ -1165,6 +1165,14 @@ class GetFormsetsArgumentCheckingAdmin(admin.ModelAdmin):
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.site_url = "/my-site-url/"
site.register(Article, ArticleAdmin)
@@ -1286,8 +1294,8 @@ site.register(ExplicitlyProvidedPK, GetFormsetsArgumentCheckingAdmin)
site.register(ImplicitlyGeneratedPK, GetFormsetsArgumentCheckingAdmin)
site.register(UserProxy)
site.register(Box)
-site.register(Country)
-site.register(Traveler)
+site.register(Country, CountryAdmin)
+site.register(Traveler, TravelerAdmin)
# Register core models we need in our tests
site.register(User, UserAdmin)
diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py
index 3037ec1c3b..1c50cb1fd3 100644
--- a/tests/admin_views/tests.py
+++ b/tests/admin_views/tests.py
@@ -6292,18 +6292,24 @@ class SeleniumTests(AdminSeleniumTestCase):
finally:
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.support.ui import Select
born_country_select_id = "id_born_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"
continent_select_id = "id_continent"
def _get_HTML_inside_element_by_id(id_):
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(
username="super", password="secret", login_url=reverse("admin:index")
)
@@ -6328,12 +6334,16 @@ class SeleniumTests(AdminSeleniumTestCase):
<option value="1" selected="">Argentina</option>
""",
)
- self.assertHTMLEqual(
- _get_HTML_inside_element_by_id(living_country_select_id),
- """
- <option value="" selected="">---------</option>
- <option value="1">Argentina</option>
- """,
+ # Argentina isn't added to the living_country select nor selected by
+ # the select2 widget.
+ self.assertEqual(
+ _get_text_inside_element_by_selector(f"#{living_country_select_id}"), ""
+ )
+ 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
# limit_choices_to.
@@ -6361,13 +6371,18 @@ class SeleniumTests(AdminSeleniumTestCase):
<option value="2">Spain</option>
""",
)
- self.assertHTMLEqual(
- _get_HTML_inside_element_by_id(living_country_select_id),
- """
- <option value="" selected="">---------</option>
- <option value="1">Argentina</option>
- <option value="2" selected="">Spain</option>
- """,
+
+ # Spain is added to the living_country select and it's also selected by
+ # the select2 widget.
+ self.assertEqual(
+ _get_text_inside_element_by_selector(f"#{living_country_select_id} 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
# limit_choices_to.
@@ -6397,13 +6412,17 @@ class SeleniumTests(AdminSeleniumTestCase):
<option value="2">Italy</option>
""",
)
- self.assertHTMLEqual(
- _get_HTML_inside_element_by_id(living_country_select_id),
- """
- <option value="" selected="">---------</option>
- <option value="1">Argentina</option>
- <option value="2" selected="">Italy</option>
- """,
+ # Italy is added to the living_country select and it's also selected by
+ # the select2 widget.
+ self.assertEqual(
+ _get_text_inside_element_by_selector(f"#{living_country_select_id} option"),
+ "Italy",
+ )
+ self.assertEqual(
+ _get_text_inside_element_by_selector(
+ f"#{living_country_select2_textbox_id}"
+ ),
+ "Italy",
)
# favorite_country_to_vacation field has no options.
self.assertHTMLEqual(