Просмотр исходного кода

Only show non-rendered field errors in toast

When script form validation fails, display error messages for fields not
in fieldsets. Fields in fieldsets show inline errors only; hidden fields
show toast notifications to provide feedback instead of failing silently.
Jason Novinger 3 месяцев назад
Родитель
Сommit
5fbae8407e
2 измененных файлов с 34 добавлено и 5 удалено
  1. 26 1
      netbox/extras/tests/test_views.py
  2. 8 4
      netbox/extras/views.py

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

@@ -930,7 +930,6 @@ class ScriptValidationErrorTest(TestCase):
 
 
     @tag('regression')
     @tag('regression')
     def test_script_validation_error_displays_message(self):
     def test_script_validation_error_displays_message(self):
-        """Test that form validation errors are displayed to the user"""
         from unittest.mock import patch
         from unittest.mock import patch
 
 
         url = reverse('extras:script', kwargs={'pk': self.script.pk})
         url = reverse('extras:script', kwargs={'pk': self.script.pk})
@@ -942,3 +941,29 @@ class ScriptValidationErrorTest(TestCase):
         messages = list(response.context['messages'])
         messages = list(response.context['messages'])
         self.assertEqual(len(messages), 1)
         self.assertEqual(len(messages), 1)
         self.assertEqual(str(messages[0]), "bar: This field is required.")
         self.assertEqual(str(messages[0]), "bar: This field is required.")
+
+    @tag('regression')
+    def test_script_validation_error_no_toast_for_fieldset_fields(self):
+        from unittest.mock import patch, PropertyMock
+
+        class FieldsetScript(PythonClass):
+            class Meta:
+                name = 'Fieldset test'
+                commit_default = False
+                fieldsets = (("Fields", ("required_field",)),)
+
+            required_field = IntegerVar(min_value=10)
+
+            def run(self, data, commit):
+                return "Complete"
+
+        url = reverse('extras:script', kwargs={'pk': self.script.pk})
+
+        with patch.object(Script, 'python_class', new_callable=PropertyMock) as mock_python_class:
+            mock_python_class.return_value = FieldsetScript
+            with patch('extras.views.get_workers_for_queue', return_value=['worker']):
+                response = self.client.post(url, {'required_field': '5', '_commit': 'true'})
+
+        self.assertEqual(response.status_code, 200)
+        messages = list(response.context['messages'])
+        self.assertEqual(len(messages), 0)

+ 8 - 4
netbox/extras/views.py

@@ -1486,10 +1486,14 @@ class ScriptView(BaseScriptView):
 
 
             return redirect('extras:script_result', job_pk=job.pk)
             return redirect('extras:script_result', job_pk=job.pk)
         else:
         else:
-            messages.error(
-                request,
-                '; '.join(f"{field}: {', '.join(errors)}" for field, errors in form.errors.items())
-            )
+            fieldset_fields = {field for _, fields in script_class.get_fieldsets() for field in fields}
+            hidden_errors = {
+                field: errors for field, errors in form.errors.items()
+                if field not in fieldset_fields
+            }
+            if hidden_errors:
+                error_msg = '; '.join(f"{field}: {', '.join(errors)}" for field, errors in hidden_errors.items())
+                messages.error(request, error_msg)
 
 
         return render(request, 'extras/script.html', {
         return render(request, 'extras/script.html', {
             'object': script,
             'object': script,