mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-19 17:59:11 -06:00
Follow-up from #2781
This commit is contained in:
parent
e97ad3f066
commit
78725b8483
@ -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
|
||||||
|
@ -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:
|
||||||
|
@ -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(
|
region_id = TreeNodeMultipleChoiceFilter(
|
||||||
method='filter_region',
|
queryset=Region.objects.all(),
|
||||||
field_name='pk',
|
field_name='cluster__site__region__in',
|
||||||
label='Region (ID)',
|
label='Region (ID)',
|
||||||
)
|
)
|
||||||
region = django_filters.CharFilter(
|
region = TreeNodeMultipleChoiceFilter(
|
||||||
method='filter_region',
|
queryset=Region.objects.all(),
|
||||||
field_name='slug',
|
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(
|
||||||
|
Loading…
Reference in New Issue
Block a user