From 48b4695ebe85c3e0a793b8870c89fb737c3d9653 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 21 Jan 2020 12:27:52 -0500 Subject: [PATCH] Fixes #3966: Fix filtering of device components by region/site --- docs/release-notes/version-2.7.md | 1 + netbox/dcim/filters.py | 48 +++++++------------------------ netbox/dcim/forms.py | 28 ++++++++++-------- 3 files changed, 27 insertions(+), 50 deletions(-) diff --git a/docs/release-notes/version-2.7.md b/docs/release-notes/version-2.7.md index 0cccc6c0b..4ec56995a 100644 --- a/docs/release-notes/version-2.7.md +++ b/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 --- diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index d749e28c6..7b278ca0e 100644 --- a/netbox/dcim/filters.py +++ b/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}) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 45ed5e136..cc18981c4 100644 --- a/netbox/dcim/forms.py +++ b/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(), - required=False, - widget=APISelect( - api_url="/api/dcim/regions/" - ) - ) - site = forms.ModelChoiceField( - 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/regions/', + value_field='slug', + filter_for={ + 'site': 'region' + } + ) + ) + site = FilterChoiceField( + queryset=Site.objects.all(), + to_field_name='slug', + widget=APISelectMultiple( + api_url="/api/dcim/sites/", + value_field="slug" + ) )