Jeremy Stretch 7 лет назад
Родитель
Сommit
78725b8483
3 измененных файлов с 11 добавлено и 30 удалено
  1. 1 0
      CHANGELOG.md
  2. 2 13
      netbox/dcim/filters.py
  3. 8 17
      netbox/virtualization/filters.py

+ 1 - 0
CHANGELOG.md

@@ -3,6 +3,7 @@ v2.5.8 (FUTURE)
 ## Bug Fixes
 ## Bug Fixes
 
 
 * [#2705](https://github.com/digitalocean/netbox/issues/2705) - Fix endpoint grouping in API docs
 * [#2705](https://github.com/digitalocean/netbox/issues/2705) - Fix endpoint grouping in API docs
+* [#2781](https://github.com/digitalocean/netbox/issues/2781) - Fix filtering of sites/devices/VMs by multiple regions
 * [#2923](https://github.com/digitalocean/netbox/issues/2923) - Provider filter form's site field should be blank by default
 * [#2923](https://github.com/digitalocean/netbox/issues/2923) - Provider filter form's site field should be blank by default
 * [#2938](https://github.com/digitalocean/netbox/issues/2938) - Enforce deterministic ordering of device components returned by API
 * [#2938](https://github.com/digitalocean/netbox/issues/2938) - Enforce deterministic ordering of device components returned by API
 * [#2939](https://github.com/digitalocean/netbox/issues/2939) - Exclude circuit terminations from API interface connections endpoint
 * [#2939](https://github.com/digitalocean/netbox/issues/2939) - Exclude circuit terminations from API interface connections endpoint

+ 2 - 13
netbox/dcim/filters.py

@@ -1,6 +1,5 @@
 import django_filters
 import django_filters
 from django.contrib.auth.models import User
 from django.contrib.auth.models import User
-from django.core.exceptions import ObjectDoesNotExist
 from django.db.models import Q
 from django.db.models import Q
 from netaddr import EUI
 from netaddr import EUI
 from netaddr.core import AddrFormatError
 from netaddr.core import AddrFormatError
@@ -508,12 +507,12 @@ class DeviceFilter(CustomFieldFilterSet):
     asset_tag = NullableCharFieldFilter()
     asset_tag = NullableCharFieldFilter()
     region_id = TreeNodeMultipleChoiceFilter(
     region_id = TreeNodeMultipleChoiceFilter(
         queryset=Region.objects.all(),
         queryset=Region.objects.all(),
-        field_name='region__in',
+        field_name='site__region__in',
         label='Region (ID)',
         label='Region (ID)',
     )
     )
     region = TreeNodeMultipleChoiceFilter(
     region = TreeNodeMultipleChoiceFilter(
         queryset=Region.objects.all(),
         queryset=Region.objects.all(),
-        field_name='region__in',
+        field_name='site__region__in',
         to_field_name='slug',
         to_field_name='slug',
         label='Region (slug)',
         label='Region (slug)',
     )
     )
@@ -613,16 +612,6 @@ class DeviceFilter(CustomFieldFilterSet):
             Q(comments__icontains=value)
             Q(comments__icontains=value)
         ).distinct()
         ).distinct()
 
 
-    def filter_region(self, queryset, name, value):
-        try:
-            region = Region.objects.get(**{name: value})
-        except ObjectDoesNotExist:
-            return queryset.none()
-        return queryset.filter(
-            Q(site__region=region) |
-            Q(site__region__in=region.get_descendants())
-        )
-
     def _mac_address(self, queryset, name, value):
     def _mac_address(self, queryset, name, value):
         value = value.strip()
         value = value.strip()
         if not value:
         if not value:

+ 8 - 17
netbox/virtualization/filters.py

@@ -7,7 +7,7 @@ from netaddr.core import AddrFormatError
 from dcim.models import DeviceRole, Interface, Platform, Region, Site
 from dcim.models import DeviceRole, Interface, Platform, Region, Site
 from extras.filters import CustomFieldFilterSet
 from extras.filters import CustomFieldFilterSet
 from tenancy.models import Tenant
 from tenancy.models import Tenant
-from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter
+from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter, TreeNodeMultipleChoiceFilter
 from .constants import VM_STATUS_CHOICES
 from .constants import VM_STATUS_CHOICES
 from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
 from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
 
 
@@ -119,14 +119,15 @@ class VirtualMachineFilter(CustomFieldFilterSet):
         queryset=Cluster.objects.all(),
         queryset=Cluster.objects.all(),
         label='Cluster (ID)',
         label='Cluster (ID)',
     )
     )
-    region_id = django_filters.NumberFilter(
-        method='filter_region',
-        field_name='pk',
+    region_id = TreeNodeMultipleChoiceFilter(
+        queryset=Region.objects.all(),
+        field_name='cluster__site__region__in',
         label='Region (ID)',
         label='Region (ID)',
     )
     )
-    region = django_filters.CharFilter(
-        method='filter_region',
-        field_name='slug',
+    region = TreeNodeMultipleChoiceFilter(
+        queryset=Region.objects.all(),
+        field_name='cluster__site__region__in',
+        to_field_name='slug',
         label='Region (slug)',
         label='Region (slug)',
     )
     )
     site_id = django_filters.ModelMultipleChoiceFilter(
     site_id = django_filters.ModelMultipleChoiceFilter(
@@ -184,16 +185,6 @@ class VirtualMachineFilter(CustomFieldFilterSet):
             Q(comments__icontains=value)
             Q(comments__icontains=value)
         )
         )
 
 
-    def filter_region(self, queryset, name, value):
-        try:
-            region = Region.objects.get(**{name: value})
-        except ObjectDoesNotExist:
-            return queryset.none()
-        return queryset.filter(
-            Q(cluster__site__region=region) |
-            Q(cluster__site__region__in=region.get_descendants())
-        )
-
 
 
 class InterfaceFilter(django_filters.FilterSet):
 class InterfaceFilter(django_filters.FilterSet):
     q = django_filters.CharFilter(
     q = django_filters.CharFilter(