Explorar el Código

Fixed #34789 -- Prevented updateRelatedSelectsOptions from
adding entries to filter_horizontal chosen box.

Co-authored-by: yokeshwaran1 <yokesh440@yahoo.com>

Devin Cox hace 9 meses
padre
commit
719a42b589

+ 2 - 2
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) {

+ 2 - 0
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

+ 3 - 0
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"),

+ 1 - 1
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"

+ 8 - 4
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),