Преглед изворни кода

Fixes #3966: Fix filtering of device components by region/site

Jeremy Stretch пре 6 година
родитељ
комит
48b4695ebe
3 измењених фајлова са 24 додато и 47 уклоњено
  1. 1 0
      docs/release-notes/version-2.7.md
  2. 10 38
      netbox/dcim/filters.py
  3. 13 9
      netbox/dcim/forms.py

+ 1 - 0
docs/release-notes/version-2.7.md

@@ -14,6 +14,7 @@
 * [#3962](https://github.com/netbox-community/netbox/issues/3962) - Fix display of unnamed devices in rack elevations
 * [#3963](https://github.com/netbox-community/netbox/issues/3963) - Restore tooltip for devices in rack elevations
 * [#3964](https://github.com/netbox-community/netbox/issues/3964) - Show borders around devices in rack elevations
+* [#3966](https://github.com/netbox-community/netbox/issues/3966) - Fix filtering of device components by region/site
 * [#3967](https://github.com/netbox-community/netbox/issues/3967) - Resolve migration of "other" interface type
 
 ---

+ 10 - 38
netbox/dcim/filters.py

@@ -695,15 +695,16 @@ class DeviceComponentFilterSet(django_filters.FilterSet):
         method='search',
         label='Search',
     )
-    region_id = django_filters.ModelMultipleChoiceFilter(
-        field_name='device__site__region',
+    region_id = TreeNodeMultipleChoiceFilter(
         queryset=Region.objects.all(),
+        field_name='device__site__region__in',
         label='Region (ID)',
     )
-    region = django_filters.ModelMultipleChoiceFilter(
-        field_name='device__site__region__in',
+    region = TreeNodeMultipleChoiceFilter(
         queryset=Region.objects.all(),
-        label='Region name (slug)',
+        field_name='device__site__region__in',
+        to_field_name='slug',
+        label='Region (slug)',
     )
     site_id = django_filters.ModelMultipleChoiceFilter(
         field_name='device__site',
@@ -713,6 +714,7 @@ class DeviceComponentFilterSet(django_filters.FilterSet):
     site = django_filters.ModelMultipleChoiceFilter(
         field_name='device__site__slug',
         queryset=Site.objects.all(),
+        to_field_name='slug',
         label='Site name (slug)',
     )
     device_id = django_filters.ModelMultipleChoiceFilter(
@@ -800,35 +802,13 @@ class PowerOutletFilterSet(DeviceComponentFilterSet):
         fields = ['id', 'name', 'feed_leg', 'description', 'connection_status']
 
 
-class InterfaceFilterSet(django_filters.FilterSet):
-    """
-    Not using DeviceComponentFilterSet for Interfaces because we need to check for VirtualChassis membership.
-    """
+class InterfaceFilterSet(DeviceComponentFilterSet):
     q = django_filters.CharFilter(
         method='search',
         label='Search',
     )
-    region_id = django_filters.ModelMultipleChoiceFilter(
-        field_name='device__site__region',
-        queryset=Region.objects.all(),
-        label='Region (ID)',
-    )
-    region = django_filters.ModelMultipleChoiceFilter(
-        field_name='device__site__region__in',
-        queryset=Region.objects.all(),
-        label='Region name (slug)',
-    )
-    site_id = django_filters.ModelMultipleChoiceFilter(
-        field_name='device__site',
-        queryset=Site.objects.all(),
-        label='Site (ID)',
-    )
-    site = django_filters.ModelMultipleChoiceFilter(
-        field_name='device__site__slug',
-        to_field_name='slug',
-        queryset=Site.objects.all(),
-        label='Site name (slug)',
-    )
+    # Override device and device_id filters from DeviceComponentFilterSet to match against any peer virtual chassis
+    # members
     device = MultiValueCharFilter(
         method='filter_device',
         field_name='name',
@@ -872,14 +852,6 @@ class InterfaceFilterSet(django_filters.FilterSet):
         model = Interface
         fields = ['id', 'name', 'connection_status', 'type', 'enabled', 'mtu', 'mgmt_only', 'mode', 'description']
 
-    def search(self, queryset, name, value):
-        if not value.strip():
-            return queryset
-        return queryset.filter(
-            Q(name__icontains=value) |
-            Q(description__icontains=value)
-        ).distinct()
-
     def filter_device(self, queryset, name, value):
         try:
             devices = Device.objects.filter(**{'{}__in'.format(name): value})

+ 13 - 9
netbox/dcim/forms.py

@@ -66,21 +66,25 @@ class DeviceComponentFilterForm(BootstrapMixin, forms.Form):
         required=False,
         label='Search'
     )
-    region = TreeNodeChoiceField(
+    region = FilterChoiceField(
         queryset=Region.objects.all(),
+        to_field_name='slug',
         required=False,
-        widget=APISelect(
-            api_url="/api/dcim/regions/"
+        widget=APISelectMultiple(
+            api_url='/api/dcim/regions/',
+            value_field='slug',
+            filter_for={
+                'site': 'region'
+            }
         )
     )
-    site = forms.ModelChoiceField(
+    site = FilterChoiceField(
         queryset=Site.objects.all(),
         to_field_name='slug',
-        required=False,
-        help_text='Name of parent site',
-        error_messages={
-            'invalid_choice': 'Site not found.',
-        }
+        widget=APISelectMultiple(
+            api_url="/api/dcim/sites/",
+            value_field="slug"
+        )
     )