Просмотр исходного кода

Fixes 17357: Use virtual chassis name as fallback for device (#18710)

Alexander Haase 11 месяцев назад
Родитель
Сommit
bf836c9bc2

+ 1 - 0
netbox/dcim/filtersets.py

@@ -1193,6 +1193,7 @@ class DeviceFilterSet(
             return queryset
         return queryset.filter(
             Q(name__icontains=value) |
+            Q(virtual_chassis__name__icontains=value) |
             Q(serial__icontains=value.strip()) |
             Q(inventoryitems__serial__icontains=value.strip()) |
             Q(asset_tag__icontains=value.strip()) |

+ 15 - 11
netbox/dcim/models/devices.py

@@ -802,14 +802,10 @@ class Device(
         verbose_name_plural = _('devices')
 
     def __str__(self):
-        if self.name and self.asset_tag:
-            return f'{self.name} ({self.asset_tag})'
-        elif self.name:
-            return self.name
-        elif self.virtual_chassis and self.asset_tag:
-            return f'{self.virtual_chassis.name}:{self.vc_position} ({self.asset_tag})'
-        elif self.virtual_chassis:
-            return f'{self.virtual_chassis.name}:{self.vc_position} ({self.pk})'
+        if self.label and self.asset_tag:
+            return f'{self.label} ({self.asset_tag})'
+        elif self.label:
+            return self.label
         elif self.device_type and self.asset_tag:
             return f'{self.device_type.manufacturer} {self.device_type.model} ({self.asset_tag})'
         elif self.device_type:
@@ -1073,14 +1069,22 @@ class Device(
             device.location = self.location
             device.save()
 
+    @property
+    def label(self):
+        """
+        Return the device name if set; otherwise return a generated name if available.
+        """
+        if self.name:
+            return self.name
+        if self.virtual_chassis:
+            return f'{self.virtual_chassis.name}:{self.vc_position}'
+
     @property
     def identifier(self):
         """
         Return the device name if set; otherwise return the Device's primary key as {pk}
         """
-        if self.name is not None:
-            return self.name
-        return '{{{}}}'.format(self.pk)
+        return self.label or '{{{}}}'.format(self.pk)
 
     @property
     def primary_ip(self):

+ 1 - 0
netbox/dcim/search.py

@@ -44,6 +44,7 @@ class DeviceIndex(SearchIndex):
         ('asset_tag', 50),
         ('serial', 60),
         ('name', 100),
+        ('virtual_chassis', 200),
         ('description', 500),
         ('comments', 5000),
     )

+ 2 - 4
netbox/dcim/svg/racks.py

@@ -30,10 +30,8 @@ STROKE_RESERVED = '#4d4dff'
 
 
 def get_device_name(device):
-    if device.virtual_chassis:
-        name = f'{device.virtual_chassis.name}:{device.vc_position}'
-    elif device.name:
-        name = device.name
+    if device.label:
+        name = device.label
     else:
         name = str(device.device_type)
     if device.devicebay_count:

+ 1 - 0
netbox/dcim/tables/devices.py

@@ -143,6 +143,7 @@ class PlatformTable(NetBoxTable):
 class DeviceTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
     name = tables.TemplateColumn(
         verbose_name=_('Name'),
+        accessor=Accessor('label'),
         template_code=DEVICE_LINK,
         linkify=True
     )

+ 26 - 0
netbox/dcim/tests/test_models.py

@@ -590,6 +590,32 @@ class DeviceTestCase(TestCase):
         device2.full_clean()
         device2.save()
 
+    def test_device_label(self):
+        device1 = Device(
+            site=Site.objects.first(),
+            device_type=DeviceType.objects.first(),
+            role=DeviceRole.objects.first(),
+            name=None,
+        )
+        self.assertEqual(device1.label, None)
+
+        device1.name = 'Test Device 1'
+        self.assertEqual(device1.label, 'Test Device 1')
+
+        virtual_chassis = VirtualChassis.objects.create(name='VC 1')
+        device2 = Device(
+            site=Site.objects.first(),
+            device_type=DeviceType.objects.first(),
+            role=DeviceRole.objects.first(),
+            name=None,
+            virtual_chassis=virtual_chassis,
+            vc_position=2,
+        )
+        self.assertEqual(device2.label, 'VC 1:2')
+
+        device2.name = 'Test Device 2'
+        self.assertEqual(device2.label, 'Test Device 2')
+
     def test_device_mismatched_site_cluster(self):
         cluster_type = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1')
         Cluster.objects.create(name='Cluster 1', type=cluster_type)