diff --git a/docs/release-notes/version-2.8.md b/docs/release-notes/version-2.8.md index f6a8dbcc3..ee9ebad0f 100644 --- a/docs/release-notes/version-2.8.md +++ b/docs/release-notes/version-2.8.md @@ -15,6 +15,7 @@ * [#4674](https://github.com/netbox-community/netbox/issues/4674) - Fix API definition for available prefix and IP address endpoints * [#4702](https://github.com/netbox-community/netbox/issues/4702) - Catch IntegrityError exception when adding a non-unique secret * [#4707](https://github.com/netbox-community/netbox/issues/4707) - Fix `prefix_count` population on VLAN API serializer +* [#4710](https://github.com/netbox-community/netbox/issues/4710) - Fix merging of form fields among custom scripts * [#4725](https://github.com/netbox-community/netbox/issues/4725) - Fix "brief" rendering of various REST API endpoints * [#4736](https://github.com/netbox-community/netbox/issues/4736) - Add cable trace endpoints for pass-through ports * [#4737](https://github.com/netbox-community/netbox/issues/4737) - Fix display of role labels in virtual machines table diff --git a/netbox/extras/forms.py b/netbox/extras/forms.py index cb9930ae2..ac4442df4 100644 --- a/netbox/extras/forms.py +++ b/netbox/extras/forms.py @@ -430,18 +430,9 @@ class ScriptForm(BootstrapMixin, forms.Form): help_text="Commit changes to the database (uncheck for a dry-run)" ) - def __init__(self, vars, *args, commit_default=True, **kwargs): - - # Dynamically populate fields for variables - for name, var in vars.items(): - self.base_fields[name] = var.as_field() - + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - # Toggle default commit behavior based on Meta option - if not commit_default: - self.fields['_commit'].initial = False - # Move _commit to the end of the form commit = self.fields.pop('_commit') self.fields['_commit'] = commit diff --git a/netbox/extras/scripts.py b/netbox/extras/scripts.py index f0ee13e7c..e41aa89e3 100644 --- a/netbox/extras/scripts.py +++ b/netbox/extras/scripts.py @@ -276,13 +276,6 @@ class BaseScript: @classmethod def _get_vars(cls): vars = OrderedDict() - - # Infer order from Meta.field_order (Python 3.5 and lower) - field_order = getattr(cls.Meta, 'field_order', []) - for name in field_order: - vars[name] = getattr(cls, name) - - # Default to order of declaration on class for name, attr in cls.__dict__.items(): if name not in vars and issubclass(attr.__class__, ScriptVariable): vars[name] = attr @@ -296,8 +289,16 @@ class BaseScript: """ Return a Django form suitable for populating the context data required to run this Script. """ - vars = self._get_vars() - form = ScriptForm(vars, data, files, initial=initial, commit_default=getattr(self.Meta, 'commit_default', True)) + # Create a dynamic ScriptForm subclass from script variables + fields = { + name: var.as_field() for name, var in self._get_vars().items() + } + FormClass = type('ScriptForm', (ScriptForm,), fields) + + form = FormClass(data, files, initial=initial) + + # Set initial "commit" checkbox state based on the script's Meta parameter + form.fields['_commit'].initial = getattr(self.Meta, 'commit_default', True) return form diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 1bfbb7abf..b6ee296e0 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -436,7 +436,6 @@ class ScriptView(PermissionRequiredMixin, View): raise Http404 def get(self, request, module, name): - script = self._get_script(module, name) form = script.as_form(initial=request.GET)