From 686633f048de15f1471fef2e9621180cbd5fcc84 Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 7 Dec 2023 13:08:58 -0800 Subject: [PATCH 1/8] 13983 split array fields in CSV data for CustomFieldChoices --- netbox/extras/forms/bulk_import.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/netbox/extras/forms/bulk_import.py b/netbox/extras/forms/bulk_import.py index 79023a74dbe..00545161abe 100644 --- a/netbox/extras/forms/bulk_import.py +++ b/netbox/extras/forms/bulk_import.py @@ -85,6 +85,17 @@ class Meta: 'name', 'description', 'extra_choices', 'order_alphabetically', ) + def clean_extra_choices(self): + if isinstance(self.cleaned_data['extra_choices'], list): + data = [] + for line in self.cleaned_data['extra_choices']: + try: + value, label = line.split(':', maxsplit=1) + except ValueError: + value, label = line, line + data.append((value, label)) + return data + class CustomLinkImportForm(CSVModelForm): content_types = CSVMultipleContentTypeField( From d677dd8b5a04614cca2919d25c618321df81932a Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 7 Dec 2023 14:55:20 -0800 Subject: [PATCH 2/8] 13983 fix help text --- netbox/extras/forms/bulk_import.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/netbox/extras/forms/bulk_import.py b/netbox/extras/forms/bulk_import.py index 00545161abe..0081551a3df 100644 --- a/netbox/extras/forms/bulk_import.py +++ b/netbox/extras/forms/bulk_import.py @@ -76,7 +76,10 @@ class CustomFieldChoiceSetImportForm(CSVModelForm): extra_choices = SimpleArrayField( base_field=forms.CharField(), required=False, - help_text=_('Comma-separated list of field choices') + help_text=_( + 'Quoted string of comma-separated field choices with optional labels separated by colon: ' + '"choice1:First Choice,choice2:Second Choice"' + ) ) class Meta: From 4cdc64c3e36cf29694a001f02a425a1c5eb84c48 Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 7 Dec 2023 15:19:23 -0800 Subject: [PATCH 3/8] 13983 update tests --- netbox/extras/tests/test_views.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/netbox/extras/tests/test_views.py b/netbox/extras/tests/test_views.py index e034abff53b..43baed077ad 100644 --- a/netbox/extras/tests/test_views.py +++ b/netbox/extras/tests/test_views.py @@ -93,6 +93,10 @@ def setUpTestData(cls): name='Choice Set 3', extra_choices=(('C1', 'Choice 1'), ('C2', 'Choice 2'), ('C3', 'Choice 3')) ), + CustomFieldChoiceSet( + name='Choice Set 4', + extra_choices=(('D1', 'Choice 1'), ('D2', 'Choice 2'), ('D3', 'Choice 3')) + ), ) CustomFieldChoiceSet.objects.bulk_create(choice_sets) @@ -103,9 +107,10 @@ def setUpTestData(cls): cls.csv_data = ( 'name,extra_choices', - 'Choice Set 4,"D1,D2,D3"', - 'Choice Set 5,"E1,E2,E3"', - 'Choice Set 6,"F1,F2,F3"', + 'Choice Set 5,"D1,D2,D3"', + 'Choice Set 6,"E1,E2,E3"', + 'Choice Set 7,"F1,F2,F3"', + 'Choice Set 8,"F1:L1,F2:L2,F3:L3"', ) cls.csv_update_data = ( @@ -113,6 +118,7 @@ def setUpTestData(cls): f'{choice_sets[0].pk},"A,B,C"', f'{choice_sets[1].pk},"A,B,C"', f'{choice_sets[2].pk},"A,B,C"', + f'{choice_sets[3].pk},"A:L1,B:L2,C:L3"', ) cls.bulk_edit_data = { From 5c0177049bdfed75aaa977031827703d9af83cae Mon Sep 17 00:00:00 2001 From: Arthur Date: Tue, 12 Dec 2023 11:43:49 -0800 Subject: [PATCH 4/8] 13983 use re for split --- netbox/extras/forms/bulk_import.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/netbox/extras/forms/bulk_import.py b/netbox/extras/forms/bulk_import.py index 0081551a3df..c938ce69d5a 100644 --- a/netbox/extras/forms/bulk_import.py +++ b/netbox/extras/forms/bulk_import.py @@ -1,3 +1,5 @@ +import re + from django import forms from django.contrib.contenttypes.models import ContentType from django.contrib.postgres.forms import SimpleArrayField @@ -93,7 +95,7 @@ def clean_extra_choices(self): data = [] for line in self.cleaned_data['extra_choices']: try: - value, label = line.split(':', maxsplit=1) + value, label = re.split(r'(? Date: Tue, 12 Dec 2023 13:20:57 -0800 Subject: [PATCH 5/8] 13983 replace escaped chars --- netbox/extras/forms/bulk_import.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/netbox/extras/forms/bulk_import.py b/netbox/extras/forms/bulk_import.py index c938ce69d5a..745268f332a 100644 --- a/netbox/extras/forms/bulk_import.py +++ b/netbox/extras/forms/bulk_import.py @@ -96,6 +96,8 @@ def clean_extra_choices(self): for line in self.cleaned_data['extra_choices']: try: value, label = re.split(r'(? Date: Tue, 12 Dec 2023 13:59:14 -0800 Subject: [PATCH 6/8] 13983 fix escape handling --- netbox/extras/forms/bulk_import.py | 2 -- netbox/extras/models/customfields.py | 6 +++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/netbox/extras/forms/bulk_import.py b/netbox/extras/forms/bulk_import.py index 745268f332a..c938ce69d5a 100644 --- a/netbox/extras/forms/bulk_import.py +++ b/netbox/extras/forms/bulk_import.py @@ -96,8 +96,6 @@ def clean_extra_choices(self): for line in self.cleaned_data['extra_choices']: try: value, label = re.split(r'(? Date: Wed, 13 Dec 2023 08:34:26 -0800 Subject: [PATCH 7/8] 13983 fix escape handling --- netbox/extras/forms/bulk_import.py | 2 ++ netbox/extras/forms/model_forms.py | 14 ++++++++++++++ netbox/extras/models/customfields.py | 6 +----- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/netbox/extras/forms/bulk_import.py b/netbox/extras/forms/bulk_import.py index c938ce69d5a..745268f332a 100644 --- a/netbox/extras/forms/bulk_import.py +++ b/netbox/extras/forms/bulk_import.py @@ -96,6 +96,8 @@ def clean_extra_choices(self): for line in self.cleaned_data['extra_choices']: try: value, label = re.split(r'(? Date: Wed, 13 Dec 2023 09:00:06 -0800 Subject: [PATCH 8/8] 13983 fix escape handling --- netbox/extras/forms/model_forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/extras/forms/model_forms.py b/netbox/extras/forms/model_forms.py index be310348d37..e193b5872ef 100644 --- a/netbox/extras/forms/model_forms.py +++ b/netbox/extras/forms/model_forms.py @@ -108,7 +108,7 @@ def __init__(self, *args, initial=None, **kwargs): super().__init__(*args, initial=initial, **kwargs) # Escape colons in extra_choices - if 'extra_choices' in self.initial: + if 'extra_choices' in self.initial and self.initial['extra_choices']: choices = [] for choice in self.initial['extra_choices']: choice = (choice[0].replace(':', '\\:'), choice[1].replace(':', '\\:'))