From 0cc2a6b2cfff58ed7da5c4ebbdda2709c29dd674 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 18 Sep 2020 13:03:38 -0400 Subject: [PATCH] Closes #5003: CSV import now accepts slug values for choice fields --- docs/release-notes/version-2.10.md | 1 + netbox/dcim/tests/test_views.py | 24 +++++++++---------- netbox/ipam/tests/test_views.py | 24 +++++++++---------- .../templates/utilities/obj_bulk_import.html | 11 +++++---- netbox/utilities/forms/fields.py | 15 ++++-------- 5 files changed, 36 insertions(+), 39 deletions(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index bcd9a55b89..d2bdf983ba 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -8,6 +8,7 @@ * [#1692](https://github.com/netbox-community/netbox/issues/1692) - Allow assigment of inventory items to parent items in web UI * [#4956](https://github.com/netbox-community/netbox/issues/4956) - Include inventory items on primary device view +* [#5003](https://github.com/netbox-community/netbox/issues/5003) - CSV import now accepts slug values for choice fields * [#5146](https://github.com/netbox-community/netbox/issues/5146) - Add custom fields support for cables, power panels, rack reservations, and virtual chassis ### Other Changes diff --git a/netbox/dcim/tests/test_views.py b/netbox/dcim/tests/test_views.py index 7afde8ed25..83d8841df0 100644 --- a/netbox/dcim/tests/test_views.py +++ b/netbox/dcim/tests/test_views.py @@ -983,9 +983,9 @@ def setUpTestData(cls): cls.csv_data = ( "device_role,manufacturer,device_type,status,name,site,rack_group,rack,position,face", - "Device Role 1,Manufacturer 1,Device Type 1,Active,Device 4,Site 1,Rack Group 1,Rack 1,10,Front", - "Device Role 1,Manufacturer 1,Device Type 1,Active,Device 5,Site 1,Rack Group 1,Rack 1,20,Front", - "Device Role 1,Manufacturer 1,Device Type 1,Active,Device 6,Site 1,Rack Group 1,Rack 1,30,Front", + "Device Role 1,Manufacturer 1,Device Type 1,active,Device 4,Site 1,Rack Group 1,Rack 1,10,front", + "Device Role 1,Manufacturer 1,Device Type 1,active,Device 5,Site 1,Rack Group 1,Rack 1,20,front", + "Device Role 1,Manufacturer 1,Device Type 1,active,Device 6,Site 1,Rack Group 1,Rack 1,30,front", ) cls.bulk_edit_data = { @@ -1267,9 +1267,9 @@ def setUpTestData(cls): cls.csv_data = ( "device,name,type", - "Device 1,Interface 4,1000BASE-T (1GE)", - "Device 1,Interface 5,1000BASE-T (1GE)", - "Device 1,Interface 6,1000BASE-T (1GE)", + "Device 1,Interface 4,1000base-t", + "Device 1,Interface 5,1000base-t", + "Device 1,Interface 6,1000base-t", ) @@ -1326,9 +1326,9 @@ def setUpTestData(cls): cls.csv_data = ( "device,name,type,rear_port,rear_port_position", - "Device 1,Front Port 4,8P8C,Rear Port 4,1", - "Device 1,Front Port 5,8P8C,Rear Port 5,1", - "Device 1,Front Port 6,8P8C,Rear Port 6,1", + "Device 1,Front Port 4,8p8c,Rear Port 4,1", + "Device 1,Front Port 5,8p8c,Rear Port 5,1", + "Device 1,Front Port 6,8p8c,Rear Port 6,1", ) @@ -1372,9 +1372,9 @@ def setUpTestData(cls): cls.csv_data = ( "device,name,type,positions", - "Device 1,Rear Port 4,8P8C,1", - "Device 1,Rear Port 5,8P8C,1", - "Device 1,Rear Port 6,8P8C,1", + "Device 1,Rear Port 4,8p8c,1", + "Device 1,Rear Port 5,8p8c,1", + "Device 1,Rear Port 6,8p8c,1", ) diff --git a/netbox/ipam/tests/test_views.py b/netbox/ipam/tests/test_views.py index 35bae013a9..7992e4ddf6 100644 --- a/netbox/ipam/tests/test_views.py +++ b/netbox/ipam/tests/test_views.py @@ -194,9 +194,9 @@ def setUpTestData(cls): cls.csv_data = ( "vrf,prefix,status", - "VRF 1,10.4.0.0/16,Active", - "VRF 1,10.5.0.0/16,Active", - "VRF 1,10.6.0.0/16,Active", + "VRF 1,10.4.0.0/16,active", + "VRF 1,10.5.0.0/16,active", + "VRF 1,10.6.0.0/16,active", ) cls.bulk_edit_data = { @@ -244,9 +244,9 @@ def setUpTestData(cls): cls.csv_data = ( "vrf,address,status", - "VRF 1,192.0.2.4/24,Active", - "VRF 1,192.0.2.5/24,Active", - "VRF 1,192.0.2.6/24,Active", + "VRF 1,192.0.2.4/24,active", + "VRF 1,192.0.2.5/24,active", + "VRF 1,192.0.2.6/24,active", ) cls.bulk_edit_data = { @@ -334,9 +334,9 @@ def setUpTestData(cls): cls.csv_data = ( "vid,name,status", - "104,VLAN104,Active", - "105,VLAN105,Active", - "106,VLAN106,Active", + "104,VLAN104,active", + "105,VLAN105,active", + "106,VLAN106,active", ) cls.bulk_edit_data = { @@ -393,9 +393,9 @@ def setUpTestData(cls): cls.csv_data = ( "device,name,protocol,port,description", - "Device 1,Service 1,TCP,1,First service", - "Device 1,Service 2,TCP,2,Second service", - "Device 1,Service 3,UDP,3,Third service", + "Device 1,Service 1,tcp,1,First service", + "Device 1,Service 2,tcp,2,Second service", + "Device 1,Service 3,udp,3,Third service", ) cls.bulk_edit_data = { diff --git a/netbox/templates/utilities/obj_bulk_import.html b/netbox/templates/utilities/obj_bulk_import.html index 9d63788ba9..9a36e1e4bc 100644 --- a/netbox/templates/utilities/obj_bulk_import.html +++ b/netbox/templates/utilities/obj_bulk_import.html @@ -66,7 +66,7 @@

{% block title %}{{ obj_type|bettertitle }} Bulk Import{% endblock %}

{% endif %} - {% if field.choice_values %} + {% if field.STATIC_CHOICES %} @@ -77,9 +77,12 @@

{% block title %}{{ obj_type|bettertitle }} Bulk Import{% endblock %}

- + + + {% for value, label in field.choices %} + {% if value %}{% endif %} + {% endfor %} + diff --git a/netbox/utilities/forms/fields.py b/netbox/utilities/forms/fields.py index 6146e00d3a..d154454126 100644 --- a/netbox/utilities/forms/fields.py +++ b/netbox/utilities/forms/fields.py @@ -117,18 +117,11 @@ class CSVChoiceField(forms.ChoiceField): """ Invert the provided set of choices to take the human-friendly label as input, and return the database value. """ - def __init__(self, choices, *args, **kwargs): - super().__init__(choices=choices, *args, **kwargs) - self.choices = [(label, label) for value, label in unpack_grouped_choices(choices)] - self.choice_values = {label: value for value, label in unpack_grouped_choices(choices)} + STATIC_CHOICES = True - def clean(self, value): - value = super().clean(value) - if not value: - return '' - if value not in self.choice_values: - raise forms.ValidationError("Invalid choice: {}".format(value)) - return self.choice_values[value] + def __init__(self, *, choices=(), **kwargs): + super().__init__(choices=choices, **kwargs) + self.choices = unpack_grouped_choices(choices) class CSVModelChoiceField(forms.ModelChoiceField):