Merge pull request #2935 from DanSheps/2781-fixsitelistfilterregion

Fixes: #2781 - Enable Filtering by Multiple Regions on Site and Device Lists
This commit is contained in:
Jeremy Stretch 2019-03-04 14:42:04 -05:00 committed by GitHub
commit e97ad3f066
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 23 deletions

View File

@ -8,7 +8,9 @@ from netaddr.core import AddrFormatError
from extras.filters import CustomFieldFilterSet from extras.filters import CustomFieldFilterSet
from tenancy.models import Tenant from tenancy.models import Tenant
from utilities.constants import COLOR_CHOICES from utilities.constants import COLOR_CHOICES
from utilities.filters import NameSlugSearchFilterSet, NullableCharFieldFilter, NumericInFilter, TagFilter from utilities.filters import (
NameSlugSearchFilterSet, NullableCharFieldFilter, NumericInFilter, TagFilter, TreeNodeMultipleChoiceFilter
)
from virtualization.models import Cluster from virtualization.models import Cluster
from .constants import * from .constants import *
from .models import ( from .models import (
@ -49,14 +51,15 @@ class SiteFilter(CustomFieldFilterSet, django_filters.FilterSet):
choices=SITE_STATUS_CHOICES, choices=SITE_STATUS_CHOICES,
null_value=None null_value=None
) )
region_id = django_filters.NumberFilter( region_id = TreeNodeMultipleChoiceFilter(
method='filter_region', queryset=Region.objects.all(),
field_name='pk', field_name='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='region__in',
to_field_name='slug',
label='Region (slug)', label='Region (slug)',
) )
tenant_id = django_filters.ModelMultipleChoiceFilter( tenant_id = django_filters.ModelMultipleChoiceFilter(
@ -95,16 +98,6 @@ class SiteFilter(CustomFieldFilterSet, django_filters.FilterSet):
pass pass
return queryset.filter(qs_filter) return queryset.filter(qs_filter)
def filter_region(self, queryset, name, value):
try:
region = Region.objects.get(**{name: value})
except ObjectDoesNotExist:
return queryset.none()
return queryset.filter(
Q(region=region) |
Q(region__in=region.get_descendants())
)
class RackGroupFilter(NameSlugSearchFilterSet): class RackGroupFilter(NameSlugSearchFilterSet):
site_id = django_filters.ModelMultipleChoiceFilter( site_id = django_filters.ModelMultipleChoiceFilter(
@ -513,14 +506,15 @@ class DeviceFilter(CustomFieldFilterSet):
) )
name = NullableCharFieldFilter() name = NullableCharFieldFilter()
asset_tag = NullableCharFieldFilter() asset_tag = NullableCharFieldFilter()
region_id = django_filters.NumberFilter( region_id = TreeNodeMultipleChoiceFilter(
method='filter_region', queryset=Region.objects.all(),
field_name='pk', field_name='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='region__in',
to_field_name='slug',
label='Region (slug)', label='Region (slug)',
) )
site_id = django_filters.ModelMultipleChoiceFilter( site_id = django_filters.ModelMultipleChoiceFilter(

View File

@ -4,6 +4,15 @@ from django.db.models import Q
from taggit.models import Tag from taggit.models import Tag
class TreeNodeMultipleChoiceFilter(django_filters.ModelMultipleChoiceFilter):
"""
Filters for a set of Models, including all descendant models within a Tree. Example: [<Region: R1>,<Region: R2>]
"""
def filter(self, qs, value):
value = [node.get_descendants(include_self=True) for node in value]
return super().filter(qs, value)
class NumericInFilter(django_filters.BaseInFilter, django_filters.NumberFilter): class NumericInFilter(django_filters.BaseInFilter, django_filters.NumberFilter):
""" """
Filters for a set of numeric values. Example: id__in=100,200,300 Filters for a set of numeric values. Example: id__in=100,200,300