Arthur 6 ngày trước cách đây
mục cha
commit
ea2f1f6189

+ 10 - 1
netbox/extras/scripts.py

@@ -723,6 +723,15 @@ def prepare_script_form(script_instance, data, files=None):
     """
     """
     data = data.copy() if data is not None else {}
     data = data.copy() if data is not None else {}
     for name, var in script_instance._get_vars().items():
     for name, var in script_instance._get_vars().items():
-        if name not in data and (initial := var.field_attrs.get('initial')) is not None:
+        if name in data:
+            continue
+        if (initial := var.field_attrs.get('initial')) is None:
+            continue
+        if isinstance(initial, (list, tuple)) and hasattr(data, 'setlist'):
+            # Assigning a list to a QueryDict stores it as a single nested value, which a
+            # multi-select widget reads back as one bogus choice. Set the values individually
+            # so a MultiChoiceVar/MultiObjectVar default binds as it does for a plain dict.
+            data.setlist(name, list(initial))
+        else:
             data[name] = initial
             data[name] = initial
     return script_instance.as_form(data=data, files=files)
     return script_instance.as_form(data=data, files=files)

+ 6 - 1
netbox/extras/tests/test_views.py

@@ -14,7 +14,7 @@ from core.models import Job, ObjectType
 from dcim.models import DeviceType, Manufacturer, Site
 from dcim.models import DeviceType, Manufacturer, Site
 from extras.choices import *
 from extras.choices import *
 from extras.models import *
 from extras.models import *
-from extras.scripts import BooleanVar, IntegerVar, StringVar
+from extras.scripts import BooleanVar, IntegerVar, MultiChoiceVar, StringVar
 from extras.scripts import Script as PythonClass
 from extras.scripts import Script as PythonClass
 from users.models import Group, ObjectPermission, User
 from users.models import Group, ObjectPermission, User
 from utilities.testing import TestCase, ViewTestCases
 from utilities.testing import TestCase, ViewTestCases
@@ -1294,6 +1294,7 @@ class ScriptDefaultBackfillTestCase(TestCase):
 
 
         label = StringVar(default='hello')
         label = StringVar(default='hello')
         flag = BooleanVar(default=True)
         flag = BooleanVar(default=True)
+        picks = MultiChoiceVar(choices=(('a', 'A'), ('b', 'B'), ('c', 'C')), default=['a', 'b'])
 
 
         def run(self, data, commit):
         def run(self, data, commit):
             return 'Complete'
             return 'Complete'
@@ -1328,6 +1329,10 @@ class ScriptDefaultBackfillTestCase(TestCase):
         data = mock_enqueue.call_args.kwargs['data']
         data = mock_enqueue.call_args.kwargs['data']
         self.assertEqual(data['label'], 'hello')
         self.assertEqual(data['label'], 'hello')
         self.assertIs(data['flag'], True)
         self.assertIs(data['flag'], True)
+        # A multi-value default must be set on the QueryDict with setlist(): a plain
+        # assignment stores the list as one nested value, which the multi-select widget
+        # then rejects as a single invalid choice.
+        self.assertEqual(data['picks'], ['a', 'b'])
 
 
 
 
 class ScriptValidationErrorTestCase(TestCase):
 class ScriptValidationErrorTestCase(TestCase):