mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-14 01:41:22 -06:00
fixes #2835 - certain model filters did not support the q query param
This commit is contained in:
parent
59f8f0c7ea
commit
613e8f05c2
@ -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
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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(
|
||||||
|
@ -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)',
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
)
|
||||||
|
@ -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)
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user