Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion netbox/extras/forms/bulk_import.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import re

from django import forms
from django.contrib.contenttypes.models import ContentType
from django.contrib.postgres.forms import SimpleArrayField
Expand Down Expand Up @@ -76,7 +78,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:
Expand All @@ -85,6 +90,19 @@ 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 = re.split(r'(?<!\\):', line, maxsplit=1)
value = value.replace('\\:', ':')
label = label.replace('\\:', ':')
except ValueError:
value, label = line, line
data.append((value, label))
return data


class CustomLinkImportForm(CSVModelForm):
content_types = CSVMultipleContentTypeField(
Expand Down
14 changes: 14 additions & 0 deletions netbox/extras/forms/model_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,25 @@ class Meta:
model = CustomFieldChoiceSet
fields = ('name', 'description', 'base_choices', 'extra_choices', 'order_alphabetically')

def __init__(self, *args, initial=None, **kwargs):
super().__init__(*args, initial=initial, **kwargs)

# Escape colons in extra_choices
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(':', '\\:'))
choices.append(choice)

self.initial['extra_choices'] = choices

def clean_extra_choices(self):
data = []
for line in self.cleaned_data['extra_choices'].splitlines():
try:
value, label = re.split(r'(?<!\\):', line, maxsplit=1)
value = value.replace('\\:', ':')
label = label.replace('\\:', ':')
except ValueError:
value, label = line, line
data.append((value, label))
Expand Down
12 changes: 9 additions & 3 deletions netbox/extras/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -103,16 +107,18 @@ 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 = (
'id,extra_choices',
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 = {
Expand Down