From c55c14ea4c48ddb5d16b0411d56c919cec34e4f1 Mon Sep 17 00:00:00 2001 From: Dillon Henschen Date: Tue, 9 May 2023 09:59:42 -0400 Subject: [PATCH] Closes #11670: Add ability to optionally import DeviceType and ModuleType weight (#12512) * 11670: Add optional weight to DeviceType import This is 1 of 2 commits to address issue #11670 To maintain consistency, the import design of the DeviceType weight follows the same pattern used for importing weight and weight units in DCIM Racks. * Closes #11670: Add weight to ModuleType import This is commit 2 of 2 to address and close #11670. To maintain consistency, the import design of the ModuleType weight follows the same pattern used for importing weight and weight units in DCIM Racks. * Merge tests; misc cleanup --------- Co-authored-by: jeremystretch --- netbox/dcim/forms/bulk_import.py | 22 ++++++++++++++++++++-- netbox/dcim/models/devices.py | 4 ++++ netbox/dcim/tests/test_views.py | 24 +++++++++++++++++++++--- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/netbox/dcim/forms/bulk_import.py b/netbox/dcim/forms/bulk_import.py index 8b7bd47ea2..cdb59e9ebe 100644 --- a/netbox/dcim/forms/bulk_import.py +++ b/netbox/dcim/forms/bulk_import.py @@ -292,12 +292,21 @@ class DeviceTypeImportForm(NetBoxModelImportForm): required=False, help_text=_('The default platform for devices of this type (optional)') ) + weight = forms.DecimalField( + required=False, + help_text=_('Device weight'), + ) + weight_unit = CSVChoiceField( + choices=WeightUnitChoices, + required=False, + help_text=_('Unit for device weight') + ) class Meta: model = DeviceType fields = [ 'manufacturer', 'default_platform', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', - 'subdevice_role', 'airflow', 'description', 'comments', + 'subdevice_role', 'airflow', 'description', 'weight', 'weight_unit', 'comments', ] @@ -306,10 +315,19 @@ class ModuleTypeImportForm(NetBoxModelImportForm): queryset=Manufacturer.objects.all(), to_field_name='name' ) + weight = forms.DecimalField( + required=False, + help_text=_('Module weight'), + ) + weight_unit = CSVChoiceField( + choices=WeightUnitChoices, + required=False, + help_text=_('Unit for module weight') + ) class Meta: model = ModuleType - fields = ['manufacturer', 'model', 'part_number', 'description', 'comments'] + fields = ['manufacturer', 'model', 'part_number', 'description', 'weight', 'weight_unit', 'comments'] class DeviceRoleImportForm(NetBoxModelImportForm): diff --git a/netbox/dcim/models/devices.py b/netbox/dcim/models/devices.py index 02c68c10a2..85a5d68707 100644 --- a/netbox/dcim/models/devices.py +++ b/netbox/dcim/models/devices.py @@ -184,6 +184,8 @@ def to_yaml(self): 'subdevice_role': self.subdevice_role, 'airflow': self.airflow, 'comments': self.comments, + 'weight': float(self.weight) if self.weight is not None else None, + 'weight_unit': self.weight_unit, } # Component templates @@ -361,6 +363,8 @@ def to_yaml(self): 'model': self.model, 'part_number': self.part_number, 'comments': self.comments, + 'weight': float(self.weight) if self.weight is not None else None, + 'weight_unit': self.weight_unit, } # Component templates diff --git a/netbox/dcim/tests/test_views.py b/netbox/dcim/tests/test_views.py index bae5a8e0bd..44e6ef2a97 100644 --- a/netbox/dcim/tests/test_views.py +++ b/netbox/dcim/tests/test_views.py @@ -681,11 +681,15 @@ def test_import_objects(self): """ IMPORT_DATA = """ manufacturer: Generic -default_platform: Platform model: TEST-1000 slug: test-1000 +default_platform: Platform u_height: 2 +is_full_depth: false +airflow: front-to-rear subdevice_role: parent +weight: 10 +weight_unit: kg comments: Test comment console-ports: - name: Console Port 1 @@ -794,8 +798,16 @@ def test_import_objects(self): self.assertHttpStatus(response, 200) device_type = DeviceType.objects.get(model='TEST-1000') - self.assertEqual(device_type.comments, 'Test comment') + self.assertEqual(device_type.manufacturer.pk, manufacturer.pk) self.assertEqual(device_type.default_platform.pk, platform.pk) + self.assertEqual(device_type.slug, 'test-1000') + self.assertEqual(device_type.u_height, 2) + self.assertFalse(device_type.is_full_depth) + self.assertEqual(device_type.airflow, DeviceAirflowChoices.AIRFLOW_FRONT_TO_REAR) + self.assertEqual(device_type.subdevice_role, SubdeviceRoleChoices.ROLE_PARENT) + self.assertEqual(device_type.weight, 10) + self.assertEqual(device_type.weight_unit, WeightUnitChoices.UNIT_KILOGRAM) + self.assertEqual(device_type.comments, 'Test comment') # Verify all of the components were created self.assertEqual(device_type.consoleporttemplates.count(), 3) @@ -1019,6 +1031,8 @@ def test_import_objects(self): IMPORT_DATA = """ manufacturer: Generic model: TEST-1000 +weight: 10 +weight_unit: lb comments: Test comment console-ports: - name: Console Port 1 @@ -1082,7 +1096,8 @@ def test_import_objects(self): """ # Create the manufacturer - Manufacturer(name='Generic', slug='generic').save() + manufacturer = Manufacturer(name='Generic', slug='generic') + manufacturer.save() # Add all required permissions to the test user self.add_permissions( @@ -1105,6 +1120,9 @@ def test_import_objects(self): self.assertHttpStatus(response, 200) module_type = ModuleType.objects.get(model='TEST-1000') + self.assertEqual(module_type.manufacturer.pk, manufacturer.pk) + self.assertEqual(module_type.weight, 10) + self.assertEqual(module_type.weight_unit, WeightUnitChoices.UNIT_POUND) self.assertEqual(module_type.comments, 'Test comment') # Verify all the components were created