1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Closes #2388: Enable filtering of devices/VMs by region

This commit is contained in:
Jeremy Stretch
2018-11-06 10:31:56 -05:00
parent 51295389c6
commit b4998f4b01
5 changed files with 56 additions and 3 deletions

View File

@ -2,6 +2,7 @@ v2.4.7 (FUTURE)
## Enhancements
* [#2388](https://github.com/digitalocean/netbox/issues/2388) - Enable filtering of devices/VMs by region
* [#2427](https://github.com/digitalocean/netbox/issues/2427) - Allow filtering of interfaces by assigned VLAN or VLAN ID
* [#2512](https://github.com/digitalocean/netbox/issues/2512) - Add device field to inventory item filter form

View File

@ -2,6 +2,7 @@ from __future__ import unicode_literals
import django_filters
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q
from netaddr import EUI
from netaddr.core import AddrFormatError
@ -456,6 +457,16 @@ class DeviceFilter(CustomFieldFilterSet, django_filters.FilterSet):
)
name = NullableCharFieldFilter()
asset_tag = NullableCharFieldFilter()
region_id = django_filters.NumberFilter(
method='filter_region',
name='pk',
label='Region (ID)',
)
region = django_filters.CharFilter(
method='filter_region',
name='slug',
label='Region (slug)',
)
site_id = django_filters.ModelMultipleChoiceFilter(
queryset=Site.objects.all(),
label='Site (ID)',
@ -538,6 +549,16 @@ class DeviceFilter(CustomFieldFilterSet, django_filters.FilterSet):
Q(comments__icontains=value)
).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):
value = value.strip()
if not value:

View File

@ -1108,6 +1108,11 @@ class DeviceBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
class DeviceFilterForm(BootstrapMixin, CustomFieldFilterForm):
model = Device
q = forms.CharField(required=False, label='Search')
region = FilterTreeNodeMultipleChoiceField(
queryset=Region.objects.all(),
to_field_name='slug',
required=False,
)
site = FilterChoiceField(
queryset=Site.objects.annotate(filter_count=Count('devices')),
to_field_name='slug',

View File

@ -1,11 +1,12 @@
from __future__ import unicode_literals
import django_filters
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q
from netaddr import EUI
from netaddr.core import AddrFormatError
from dcim.models import DeviceRole, Interface, Platform, Site
from dcim.models import DeviceRole, Interface, Platform, Region, Site
from extras.filters import CustomFieldFilterSet
from tenancy.models import Tenant
from utilities.filters import NumericInFilter
@ -116,6 +117,16 @@ class VirtualMachineFilter(CustomFieldFilterSet):
queryset=Cluster.objects.all(),
label='Cluster (ID)',
)
region_id = django_filters.NumberFilter(
method='filter_region',
name='pk',
label='Region (ID)',
)
region = django_filters.CharFilter(
method='filter_region',
name='slug',
label='Region (slug)',
)
site_id = django_filters.ModelMultipleChoiceFilter(
name='cluster__site',
queryset=Site.objects.all(),
@ -173,6 +184,16 @@ class VirtualMachineFilter(CustomFieldFilterSet):
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):
virtual_machine_id = django_filters.ModelMultipleChoiceFilter(

View File

@ -16,8 +16,8 @@ from tenancy.models import Tenant
from utilities.forms import (
AnnotatedMultipleChoiceField, APISelect, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect,
ChainedFieldsMixin, ChainedModelChoiceField, ChainedModelMultipleChoiceField, CommentField, ComponentForm,
ConfirmationForm, CSVChoiceField, ExpandableNameField, FilterChoiceField, JSONField, SlugField, SmallTextarea,
add_blank_choice
ConfirmationForm, CSVChoiceField, ExpandableNameField, FilterChoiceField, FilterTreeNodeMultipleChoiceField,
JSONField, SlugField, SmallTextarea, add_blank_choice,
)
from .constants import VM_STATUS_CHOICES
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
@ -386,6 +386,11 @@ class VirtualMachineFilterForm(BootstrapMixin, CustomFieldFilterForm):
queryset=Cluster.objects.annotate(filter_count=Count('virtual_machines')),
label='Cluster'
)
region = FilterTreeNodeMultipleChoiceField(
queryset=Region.objects.all(),
to_field_name='slug',
required=False,
)
site = FilterChoiceField(
queryset=Site.objects.annotate(filter_count=Count('clusters__virtual_machines')),
to_field_name='slug',