fixes #2835 - certain model filters did not support the q query param

This commit is contained in:
John Anderson 2019-01-31 13:36:30 -05:00
parent 59f8f0c7ea
commit 613e8f05c2
8 changed files with 67 additions and 47 deletions

View File

@ -9,6 +9,7 @@ v2.5.5 (FUTURE)
* [#2824](https://github.com/digitalocean/netbox/issues/2824) - Fix template exception when viewing rack elevations list * [#2824](https://github.com/digitalocean/netbox/issues/2824) - Fix template exception when viewing rack elevations list
* [#2833](https://github.com/digitalocean/netbox/issues/2833) - Fix form widget for front port template creation * [#2833](https://github.com/digitalocean/netbox/issues/2833) - Fix form widget for front port template creation
* [#2835](https://github.com/digitalocean/netbox/issues/2835) - Fix certain model filters did not support the `q` query param
--- ---

View File

@ -4,7 +4,7 @@ from django.db.models import Q
from dcim.models import Site from dcim.models import 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 NumericInFilter, TagFilter from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter
from .constants import CIRCUIT_STATUS_CHOICES from .constants import CIRCUIT_STATUS_CHOICES
from .models import Provider, Circuit, CircuitTermination, CircuitType from .models import Provider, Circuit, CircuitTermination, CircuitType
@ -47,7 +47,7 @@ class ProviderFilter(CustomFieldFilterSet, django_filters.FilterSet):
) )
class CircuitTypeFilter(django_filters.FilterSet): class CircuitTypeFilter(NameSlugSearchFilterSet):
class Meta: class Meta:
model = CircuitType model = CircuitType

View File

@ -8,7 +8,7 @@ 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 NullableCharFieldFilter, NumericInFilter, TagFilter from utilities.filters import NameSlugSearchFilterSet, NullableCharFieldFilter, NumericInFilter, TagFilter
from virtualization.models import Cluster from virtualization.models import Cluster
from .constants import * from .constants import *
from .models import ( from .models import (
@ -19,11 +19,7 @@ from .models import (
) )
class RegionFilter(django_filters.FilterSet): class RegionFilter(NameSlugSearchFilterSet):
q = django_filters.CharFilter(
method='search',
label='Search',
)
parent_id = django_filters.ModelMultipleChoiceFilter( parent_id = django_filters.ModelMultipleChoiceFilter(
queryset=Region.objects.all(), queryset=Region.objects.all(),
label='Parent region (ID)', label='Parent region (ID)',
@ -39,15 +35,6 @@ class RegionFilter(django_filters.FilterSet):
model = Region model = Region
fields = ['name', 'slug'] fields = ['name', 'slug']
def search(self, queryset, name, value):
if not value.strip():
return queryset
qs_filter = (
Q(name__icontains=value) |
Q(slug__icontains=value)
)
return queryset.filter(qs_filter)
class SiteFilter(CustomFieldFilterSet, django_filters.FilterSet): class SiteFilter(CustomFieldFilterSet, django_filters.FilterSet):
id__in = NumericInFilter( id__in = NumericInFilter(
@ -119,11 +106,7 @@ class SiteFilter(CustomFieldFilterSet, django_filters.FilterSet):
) )
class RackGroupFilter(django_filters.FilterSet): class RackGroupFilter(NameSlugSearchFilterSet):
q = django_filters.CharFilter(
method='search',
label='Search',
)
site_id = django_filters.ModelMultipleChoiceFilter( site_id = django_filters.ModelMultipleChoiceFilter(
queryset=Site.objects.all(), queryset=Site.objects.all(),
label='Site (ID)', label='Site (ID)',
@ -139,17 +122,8 @@ class RackGroupFilter(django_filters.FilterSet):
model = RackGroup model = RackGroup
fields = ['site_id', 'name', 'slug'] fields = ['site_id', 'name', 'slug']
def search(self, queryset, name, value):
if not value.strip():
return queryset
qs_filter = (
Q(name__icontains=value) |
Q(slug__icontains=value)
)
return queryset.filter(qs_filter)
class RackRoleFilter(NameSlugSearchFilterSet):
class RackRoleFilter(django_filters.FilterSet):
class Meta: class Meta:
model = RackRole model = RackRole
@ -303,7 +277,7 @@ class RackReservationFilter(django_filters.FilterSet):
) )
class ManufacturerFilter(django_filters.FilterSet): class ManufacturerFilter(NameSlugSearchFilterSet):
class Meta: class Meta:
model = Manufacturer model = Manufacturer
@ -393,7 +367,7 @@ class DeviceTypeFilter(CustomFieldFilterSet):
) )
class DeviceTypeComponentFilterSet(django_filters.FilterSet): class DeviceTypeComponentFilterSet(NameSlugSearchFilterSet):
devicetype_id = django_filters.ModelMultipleChoiceFilter( devicetype_id = django_filters.ModelMultipleChoiceFilter(
queryset=DeviceType.objects.all(), queryset=DeviceType.objects.all(),
field_name='device_type_id', field_name='device_type_id',
@ -457,14 +431,14 @@ class DeviceBayTemplateFilter(DeviceTypeComponentFilterSet):
fields = ['name'] fields = ['name']
class DeviceRoleFilter(django_filters.FilterSet): class DeviceRoleFilter(NameSlugSearchFilterSet):
class Meta: class Meta:
model = DeviceRole model = DeviceRole
fields = ['name', 'slug', 'color', 'vm_role'] fields = ['name', 'slug', 'color', 'vm_role']
class PlatformFilter(django_filters.FilterSet): class PlatformFilter(NameSlugSearchFilterSet):
manufacturer_id = django_filters.ModelMultipleChoiceFilter( manufacturer_id = django_filters.ModelMultipleChoiceFilter(
field_name='manufacturer', field_name='manufacturer',
queryset=Manufacturer.objects.all(), queryset=Manufacturer.objects.all(),
@ -696,6 +670,10 @@ class DeviceFilter(CustomFieldFilterSet):
class DeviceComponentFilterSet(django_filters.FilterSet): class DeviceComponentFilterSet(django_filters.FilterSet):
q = django_filters.CharFilter(
method='search',
label='Search',
)
device_id = django_filters.ModelChoiceFilter( device_id = django_filters.ModelChoiceFilter(
queryset=Device.objects.all(), queryset=Device.objects.all(),
label='Device (ID)', label='Device (ID)',
@ -707,6 +685,13 @@ class DeviceComponentFilterSet(django_filters.FilterSet):
) )
tag = TagFilter() tag = TagFilter()
def search(self, queryset, name, value):
if not value.strip():
return queryset
return queryset.filter(
Q(name__icontains=value)
)
class ConsolePortFilter(DeviceComponentFilterSet): class ConsolePortFilter(DeviceComponentFilterSet):
cabled = django_filters.BooleanFilter( cabled = django_filters.BooleanFilter(

View File

@ -7,7 +7,7 @@ from netaddr.core import AddrFormatError
from dcim.models import Site, Device, Interface from dcim.models import Site, Device, Interface
from extras.filters import CustomFieldFilterSet from extras.filters import CustomFieldFilterSet
from tenancy.models import Tenant from tenancy.models import Tenant
from utilities.filters import NumericInFilter, TagFilter from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter
from virtualization.models import VirtualMachine from virtualization.models import VirtualMachine
from .constants import IPADDRESS_ROLE_CHOICES, IPADDRESS_STATUS_CHOICES, PREFIX_STATUS_CHOICES, VLAN_STATUS_CHOICES from .constants import IPADDRESS_ROLE_CHOICES, IPADDRESS_STATUS_CHOICES, PREFIX_STATUS_CHOICES, VLAN_STATUS_CHOICES
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
@ -48,7 +48,7 @@ class VRFFilter(CustomFieldFilterSet, django_filters.FilterSet):
fields = ['name', 'rd', 'enforce_unique'] fields = ['name', 'rd', 'enforce_unique']
class RIRFilter(django_filters.FilterSet): class RIRFilter(NameSlugSearchFilterSet):
id__in = NumericInFilter( id__in = NumericInFilter(
field_name='id', field_name='id',
lookup_expr='in' lookup_expr='in'
@ -96,7 +96,11 @@ class AggregateFilter(CustomFieldFilterSet, django_filters.FilterSet):
return queryset.filter(qs_filter) return queryset.filter(qs_filter)
class RoleFilter(django_filters.FilterSet): class RoleFilter(NameSlugSearchFilterSet):
q = django_filters.CharFilter(
method='search',
label='Search',
)
class Meta: class Meta:
model = Role model = Role
@ -373,7 +377,7 @@ class IPAddressFilter(CustomFieldFilterSet, django_filters.FilterSet):
return queryset.none() return queryset.none()
class VLANGroupFilter(django_filters.FilterSet): class VLANGroupFilter(NameSlugSearchFilterSet):
site_id = django_filters.ModelMultipleChoiceFilter( site_id = django_filters.ModelMultipleChoiceFilter(
queryset=Site.objects.all(), queryset=Site.objects.all(),
label='Site (ID)', label='Site (ID)',

View File

@ -3,11 +3,11 @@ from django.db.models import Q
from dcim.models import Device from dcim.models import Device
from extras.filters import CustomFieldFilterSet from extras.filters import CustomFieldFilterSet
from utilities.filters import NumericInFilter, TagFilter from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter
from .models import Secret, SecretRole from .models import Secret, SecretRole
class SecretRoleFilter(django_filters.FilterSet): class SecretRoleFilter(NameSlugSearchFilterSet):
class Meta: class Meta:
model = SecretRole model = SecretRole

View File

@ -2,11 +2,11 @@ import django_filters
from django.db.models import Q from django.db.models import Q
from extras.filters import CustomFieldFilterSet from extras.filters import CustomFieldFilterSet
from utilities.filters import NumericInFilter, TagFilter from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter
from .models import Tenant, TenantGroup from .models import Tenant, TenantGroup
class TenantGroupFilter(django_filters.FilterSet): class TenantGroupFilter(NameSlugSearchFilterSet):
class Meta: class Meta:
model = TenantGroup model = TenantGroup

View File

@ -1,4 +1,5 @@
import django_filters import django_filters
from django.db.models import Q
from taggit.models import Tag from taggit.models import Tag
@ -35,3 +36,21 @@ class TagFilter(django_filters.ModelMultipleChoiceFilter):
kwargs.setdefault('queryset', Tag.objects.all()) kwargs.setdefault('queryset', Tag.objects.all())
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
class NameSlugSearchFilterSet(django_filters.FilterSet):
"""
A base class for adding the search method to models which only expose the `name` and `slug` fields
"""
q = django_filters.CharFilter(
method='search',
label='Search',
)
def search(self, queryset, name, value):
if not value.strip():
return queryset
return queryset.filter(
Q(name__icontains=value) |
Q(slug__icontains=value)
)

View File

@ -7,19 +7,19 @@ 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 NumericInFilter, TagFilter from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter
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
class ClusterTypeFilter(django_filters.FilterSet): class ClusterTypeFilter(NameSlugSearchFilterSet):
class Meta: class Meta:
model = ClusterType model = ClusterType
fields = ['name', 'slug'] fields = ['name', 'slug']
class ClusterGroupFilter(django_filters.FilterSet): class ClusterGroupFilter(NameSlugSearchFilterSet):
class Meta: class Meta:
model = ClusterGroup model = ClusterGroup
@ -196,6 +196,10 @@ class VirtualMachineFilter(CustomFieldFilterSet):
class InterfaceFilter(django_filters.FilterSet): class InterfaceFilter(django_filters.FilterSet):
q = django_filters.CharFilter(
method='search',
label='Search',
)
virtual_machine_id = django_filters.ModelMultipleChoiceFilter( virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
field_name='virtual_machine', field_name='virtual_machine',
queryset=VirtualMachine.objects.all(), queryset=VirtualMachine.objects.all(),
@ -225,3 +229,10 @@ class InterfaceFilter(django_filters.FilterSet):
return queryset.filter(mac_address=mac) return queryset.filter(mac_address=mac)
except AddrFormatError: except AddrFormatError:
return queryset.none() return queryset.none()
def search(self, queryset, name, value):
if not value.strip():
return queryset
return queryset.filter(
Q(name__icontains=value)
)