diff --git a/docs/additional-features/custom-scripts.md b/docs/additional-features/custom-scripts.md index c00f54d4c..8d453f668 100644 --- a/docs/additional-features/custom-scripts.md +++ b/docs/additional-features/custom-scripts.md @@ -119,6 +119,23 @@ Stored a numeric integer. Options include: A true/false flag. This field has no options beyond the defaults. +### ChoiceVar + +A set of choices from which the user can select one. + +* `choices` - A list of `(value, label)` tuples representing the available choices. For example: + +```python +CHOICES = ( + ('n', 'North'), + ('s', 'South'), + ('e', 'East'), + ('w', 'West') +) + +direction = ChoiceVar(choices=CHOICES) +``` + ### ObjectVar A NetBox object. The list of available objects is defined by the queryset parameter. Each instance of this variable is limited to a single object type. diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index 9321477b7..32a631fb0 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -4,6 +4,7 @@ * [#3445](https://github.com/netbox-community/netbox/issues/3445) - Add support for additional user defined headers to be added to webhook requests * [#3499](https://github.com/netbox-community/netbox/issues/3499) - Add `ca_file_path` to Webhook model to support user supplied CA certificate verification of webhook requests +* [#3594](https://github.com/netbox-community/netbox/issues/3594) - Add ChoiceVar for custom scripts ## Bug Fixes diff --git a/netbox/extras/scripts.py b/netbox/extras/scripts.py index f83cffdea..4e0934a6a 100644 --- a/netbox/extras/scripts.py +++ b/netbox/extras/scripts.py @@ -24,6 +24,7 @@ from .signals import purge_changelog __all__ = [ 'BaseScript', 'BooleanVar', + 'ChoiceVar', 'FileVar', 'IntegerVar', 'IPNetworkVar', @@ -133,6 +134,27 @@ class BooleanVar(ScriptVariable): self.field_attrs['required'] = False +class ChoiceVar(ScriptVariable): + """ + Select one of several predefined static choices, passed as a list of two-tuples. Example: + + color = ChoiceVar( + choices=( + ('#ff0000', 'Red'), + ('#00ff00', 'Green'), + ('#0000ff', 'Blue') + ) + ) + """ + form_field = forms.ChoiceField + + def __init__(self, choices, *args, **kwargs): + super().__init__(*args, **kwargs) + + # Set field choices + self.field_attrs['choices'] = choices + + class ObjectVar(ScriptVariable): """ NetBox object representation. The provided QuerySet will determine the choices available. diff --git a/netbox/extras/tests/test_scripts.py b/netbox/extras/tests/test_scripts.py index f9fc98ff2..26e12772f 100644 --- a/netbox/extras/tests/test_scripts.py +++ b/netbox/extras/tests/test_scripts.py @@ -99,6 +99,31 @@ class ScriptVariablesTest(TestCase): self.assertTrue(form.is_valid()) self.assertEqual(form.cleaned_data['var1'], False) + def test_choicevar(self): + + CHOICES = ( + ('ff0000', 'Red'), + ('00ff00', 'Green'), + ('0000ff', 'Blue') + ) + + class TestScript(Script): + + var1 = ChoiceVar( + choices=CHOICES + ) + + # Validate valid choice + data = {'var1': CHOICES[0][0]} + form = TestScript().as_form(data) + self.assertTrue(form.is_valid()) + self.assertEqual(form.cleaned_data['var1'], CHOICES[0][0]) + + # Validate invalid choices + data = {'var1': 'taupe'} + form = TestScript().as_form(data) + self.assertFalse(form.is_valid()) + def test_objectvar(self): class TestScript(Script):