Przeglądaj źródła

14948 add has_virtual_device_contexts filter to device (#16209)

* 14948 add has_virtual_device_cnotexts filter to device

* 14948 make singular

* 14948 add test
Arthur Hanson 1 rok temu
rodzic
commit
753c4021eb

+ 10 - 0
netbox/dcim/filtersets.py

@@ -1100,6 +1100,10 @@ class DeviceFilterSet(
         queryset=IPAddress.objects.all(),
         label=_('OOB IP (ID)'),
     )
+    has_virtual_device_context = django_filters.BooleanFilter(
+        method='_has_virtual_device_context',
+        label=_('Has virtual device context'),
+    )
 
     class Meta:
         model = Device
@@ -1176,6 +1180,12 @@ class DeviceFilterSet(
     def _device_bays(self, queryset, name, value):
         return queryset.exclude(devicebays__isnull=value)
 
+    def _has_virtual_device_context(self, queryset, name, value):
+        params = Q(vdcs__isnull=False)
+        if value:
+            return queryset.filter(params).distinct()
+        return queryset.exclude(params)
+
 
 class VirtualDeviceContextFilterSet(NetBoxModelFilterSet, TenancyFilterSet, PrimaryIPFilterSet):
     device_id = django_filters.ModelMultipleChoiceFilter(

+ 8 - 0
netbox/dcim/forms/filtersets.py

@@ -657,6 +657,7 @@ class DeviceFilterForm(
         ),
         FieldSet(
             'has_primary_ip', 'has_oob_ip', 'virtual_chassis_member', 'config_template_id', 'local_context_data',
+            'has_virtual_device_context',
             name=_('Miscellaneous')
         )
     )
@@ -813,6 +814,13 @@ class DeviceFilterForm(
             choices=BOOLEAN_WITH_BLANK_CHOICES
         )
     )
+    has_virtual_device_context = forms.NullBooleanField(
+        required=False,
+        label=_('Has virtual device contexts'),
+        widget=forms.Select(
+            choices=BOOLEAN_WITH_BLANK_CHOICES
+        )
+    )
     tag = TagFilterField(model)
 
 

+ 9 - 0
netbox/dcim/tests/test_filtersets.py

@@ -2103,6 +2103,9 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
         Device.objects.filter(pk=devices[0].pk).update(virtual_chassis=virtual_chassis, vc_position=1, vc_priority=1)
         Device.objects.filter(pk=devices[1].pk).update(virtual_chassis=virtual_chassis, vc_position=2, vc_priority=2)
 
+        # VirtualDeviceContext assignment for filtering
+        VirtualDeviceContext.objects.create(device=devices[0], name="VDC 1", identifier=1, status='active')
+
     def test_q(self):
         params = {'q': 'foobar1'}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
@@ -2336,6 +2339,12 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
         params = {'tenant_group': [tenant_groups[0].slug, tenant_groups[1].slug]}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
+    def test_has_virtual_device_context(self):
+        params = {'has_virtual_device_context': 'true'}
+        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
+        params = {'has_virtual_device_context': 'false'}
+        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
+
 
 class ModuleTestCase(TestCase, ChangeLoggedFilterSetTests):
     queryset = Module.objects.all()