summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDevin Cox <dcox@surefyre.co>2024-06-12 11:35:12 +0200
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2024-06-14 14:05:11 +0200
commit49a3a8d9a22ebcb29fdc4bacaa204f0bd2a6abf6 (patch)
treed6a8df6172107a3b42cd7340a9e830cf3283fac5
parentfed3efda15f9ff96714f738c44aa823d63762a8c (diff)
[5.1.x] Fixed #34789 -- Prevented updateRelatedSelectsOptions from
adding entries to filter_horizontal chosen box. Co-authored-by: yokeshwaran1 <yokesh440@yahoo.com> Backport of 719a42b589d7551fc84708044b9e984ce723c8a2 from main.
-rw-r--r--django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js4
-rw-r--r--django/contrib/admin/widgets.py2
-rw-r--r--tests/admin_views/test_related_object_lookups.py3
-rw-r--r--tests/admin_widgets/tests.py2
-rw-r--r--tests/modeladmin/tests.py12
5 files changed, 16 insertions, 7 deletions
diff --git a/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js b/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js
index 32e3f5b840..bc3accea37 100644
--- a/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js
+++ b/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js
@@ -96,8 +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)];
- // Exclude autocomplete selects.
- const selectsRelated = document.querySelectorAll(`[data-model-ref="${modelName}"] select:not(.admin-autocomplete)`);
+ // Select elements with a specific model reference and context of "available-source".
+ const selectsRelated = document.querySelectorAll(`[data-model-ref="${modelName}"] [data-context="available-source"]`);
selectsRelated.forEach(function(select) {
if (currentSelect === select) {
diff --git a/django/contrib/admin/widgets.py b/django/contrib/admin/widgets.py
index 260ff33ca5..00e92bf42d 100644
--- a/django/contrib/admin/widgets.py
+++ b/django/contrib/admin/widgets.py
@@ -272,6 +272,8 @@ class RelatedFieldWidgetWrapper(forms.Widget):
self.can_add_related = can_add_related
# XXX: The UX does not support multiple selected values.
multiple = getattr(widget, "allow_multiple_selected", False)
+ if not isinstance(widget, AutocompleteMixin):
+ self.attrs["data-context"] = "available-source"
self.can_change_related = not multiple and can_change_related
# XXX: The deletion UX can be confusing when dealing with cascading deletion.
cascade = getattr(rel, "on_delete", None) is CASCADE
diff --git a/tests/admin_views/test_related_object_lookups.py b/tests/admin_views/test_related_object_lookups.py
index c10a5568d5..761819a50f 100644
--- a/tests/admin_views/test_related_object_lookups.py
+++ b/tests/admin_views/test_related_object_lookups.py
@@ -110,6 +110,9 @@ class SeleniumTests(AdminSeleniumTestCase):
<option value="1" selected>{interesting_name}</option>
""",
)
+ # Check the newly added instance is not also added in the "to" box.
+ m2m_to = self.selenium.find_element(By.ID, "id_m2m_to")
+ self.assertHTMLEqual(m2m_to.get_attribute("innerHTML"), "")
m2m_box = self.selenium.find_element(By.ID, "id_m2m_from")
self.assertHTMLEqual(
m2m_box.get_attribute("innerHTML"),
diff --git a/tests/admin_widgets/tests.py b/tests/admin_widgets/tests.py
index 4d18849692..6f009a6f3f 100644
--- a/tests/admin_widgets/tests.py
+++ b/tests/admin_widgets/tests.py
@@ -948,7 +948,7 @@ class RelatedFieldWidgetWrapperTests(SimpleTestCase):
output = wrapper.render("stream", "value")
expected = """
<div class="related-widget-wrapper" data-model-ref="releaseevent">
- <select name="stream">
+ <select name="stream" data-context="available-source">
</select>
<a class="related-widget-wrapper-link add-related" id="add_id_stream"
data-popup="yes" title="Add another release event"
diff --git a/tests/modeladmin/tests.py b/tests/modeladmin/tests.py
index de8d26ae46..e8b59ed0bf 100644
--- a/tests/modeladmin/tests.py
+++ b/tests/modeladmin/tests.py
@@ -662,7 +662,8 @@ class ModelAdminTests(TestCase):
self.assertHTMLEqual(
str(form["main_band"]),
'<div class="related-widget-wrapper" data-model-ref="band">'
- '<select name="main_band" id="id_main_band" required>'
+ '<select data-context="available-source" '
+ 'name="main_band" id="id_main_band" required>'
'<option value="" selected>---------</option>'
'<option value="%d">The Beatles</option>'
'<option value="%d">The Doors</option>'
@@ -685,7 +686,8 @@ class ModelAdminTests(TestCase):
self.assertHTMLEqual(
str(form["main_band"]),
'<div class="related-widget-wrapper" data-model-ref="band">'
- '<select name="main_band" id="id_main_band" required>'
+ '<select data-context="available-source" '
+ 'name="main_band" id="id_main_band" required>'
'<option value="" selected>---------</option>'
'<option value="%d">The Doors</option>'
"</select></div>" % self.band.id,
@@ -779,7 +781,8 @@ class ModelAdminTests(TestCase):
type(cmafa.base_fields["main_band"].widget.widget), AdminRadioSelect
)
self.assertEqual(
- cmafa.base_fields["main_band"].widget.attrs, {"class": "radiolist inline"}
+ cmafa.base_fields["main_band"].widget.attrs,
+ {"class": "radiolist inline", "data-context": "available-source"},
)
self.assertEqual(
list(cmafa.base_fields["main_band"].widget.choices),
@@ -790,7 +793,8 @@ class ModelAdminTests(TestCase):
type(cmafa.base_fields["opening_band"].widget.widget), AdminRadioSelect
)
self.assertEqual(
- cmafa.base_fields["opening_band"].widget.attrs, {"class": "radiolist"}
+ cmafa.base_fields["opening_band"].widget.attrs,
+ {"class": "radiolist", "data-context": "available-source"},
)
self.assertEqual(
list(cmafa.base_fields["opening_band"].widget.choices),