diff --git a/netbox/circuits/filtersets.py b/netbox/circuits/filtersets.py index 7775255fc..d693c5fb9 100644 --- a/netbox/circuits/filtersets.py +++ b/netbox/circuits/filtersets.py @@ -6,7 +6,7 @@ from django.utils.translation import gettext as _ from dcim.filtersets import CabledObjectFilterSet from dcim.models import Interface, Location, Region, Site, SiteGroup from ipam.models import ASN -from netbox.filtersets import NetBoxModelFilterSet, OrganizationalModelFilterSet +from netbox.filtersets import NetBoxModelFilterSet, OrganizationalModelFilterSet, PrimaryModelFilterSet from tenancy.filtersets import ContactModelFilterSet, TenancyFilterSet from utilities.filters import ( ContentTypeFilter, MultiValueCharFilter, MultiValueNumberFilter, TreeNodeMultipleChoiceFilter, @@ -29,7 +29,7 @@ __all__ = ( ) -class ProviderFilterSet(NetBoxModelFilterSet, ContactModelFilterSet): +class ProviderFilterSet(PrimaryModelFilterSet, ContactModelFilterSet): region_id = TreeNodeMultipleChoiceFilter( queryset=Region.objects.all(), field_name='circuits__terminations___region', @@ -95,7 +95,7 @@ class ProviderFilterSet(NetBoxModelFilterSet, ContactModelFilterSet): ) -class ProviderAccountFilterSet(NetBoxModelFilterSet, ContactModelFilterSet): +class ProviderAccountFilterSet(PrimaryModelFilterSet, ContactModelFilterSet): provider_id = django_filters.ModelMultipleChoiceFilter( queryset=Provider.objects.all(), label=_('Provider (ID)'), @@ -122,7 +122,7 @@ class ProviderAccountFilterSet(NetBoxModelFilterSet, ContactModelFilterSet): ).distinct() -class ProviderNetworkFilterSet(NetBoxModelFilterSet): +class ProviderNetworkFilterSet(PrimaryModelFilterSet): provider_id = django_filters.ModelMultipleChoiceFilter( queryset=Provider.objects.all(), label=_('Provider (ID)'), @@ -156,7 +156,7 @@ class CircuitTypeFilterSet(OrganizationalModelFilterSet): fields = ('id', 'name', 'slug', 'color', 'description') -class CircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet): +class CircuitFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ContactModelFilterSet): provider_id = django_filters.ModelMultipleChoiceFilter( queryset=Provider.objects.all(), label=_('Provider (ID)'), @@ -475,7 +475,7 @@ class VirtualCircuitTypeFilterSet(OrganizationalModelFilterSet): fields = ('id', 'name', 'slug', 'color', 'description') -class VirtualCircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet): +class VirtualCircuitFilterSet(PrimaryModelFilterSet, TenancyFilterSet): provider_id = django_filters.ModelMultipleChoiceFilter( field_name='provider_network__provider', queryset=Provider.objects.all(), diff --git a/netbox/core/filtersets.py b/netbox/core/filtersets.py index 391ac02f7..0c660fd3e 100644 --- a/netbox/core/filtersets.py +++ b/netbox/core/filtersets.py @@ -3,7 +3,7 @@ from django.contrib.contenttypes.models import ContentType from django.db.models import Q from django.utils.translation import gettext as _ -from netbox.filtersets import BaseFilterSet, ChangeLoggedModelFilterSet, NetBoxModelFilterSet +from netbox.filtersets import BaseFilterSet, ChangeLoggedModelFilterSet, PrimaryModelFilterSet from netbox.utils import get_data_backend_choices from users.models import User from utilities.filters import ContentTypeFilter @@ -20,7 +20,7 @@ __all__ = ( ) -class DataSourceFilterSet(NetBoxModelFilterSet): +class DataSourceFilterSet(PrimaryModelFilterSet): type = django_filters.MultipleChoiceFilter( choices=get_data_backend_choices, null_value=None diff --git a/netbox/dcim/filtersets.py b/netbox/dcim/filtersets.py index 04ba3b00d..ba7aa30c1 100644 --- a/netbox/dcim/filtersets.py +++ b/netbox/dcim/filtersets.py @@ -11,8 +11,8 @@ from ipam.filtersets import PrimaryIPFilterSet from ipam.models import ASN, IPAddress, VLANTranslationPolicy, VRF from netbox.choices import ColorChoices from netbox.filtersets import ( - AttributeFiltersMixin, BaseFilterSet, ChangeLoggedModelFilterSet, NestedGroupModelFilterSet, NetBoxModelFilterSet, - OrganizationalModelFilterSet, + AttributeFiltersMixin, BaseFilterSet, ChangeLoggedModelFilterSet, NestedGroupModelFilterSet, + OrganizationalModelFilterSet, PrimaryModelFilterSet, ) from tenancy.filtersets import TenancyFilterSet, ContactModelFilterSet from tenancy.models import * @@ -143,7 +143,7 @@ class SiteGroupFilterSet(NestedGroupModelFilterSet, ContactModelFilterSet): fields = ('id', 'name', 'slug', 'description') -class SiteFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet): +class SiteFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ContactModelFilterSet): status = django_filters.MultipleChoiceFilter( choices=SiteStatusChoices, null_value=None @@ -293,7 +293,7 @@ class RackRoleFilterSet(OrganizationalModelFilterSet): fields = ('id', 'name', 'slug', 'color', 'description') -class RackTypeFilterSet(NetBoxModelFilterSet): +class RackTypeFilterSet(PrimaryModelFilterSet): manufacturer_id = django_filters.ModelMultipleChoiceFilter( queryset=Manufacturer.objects.all(), label=_('Manufacturer (ID)'), @@ -328,7 +328,7 @@ class RackTypeFilterSet(NetBoxModelFilterSet): ) -class RackFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet): +class RackFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ContactModelFilterSet): region_id = TreeNodeMultipleChoiceFilter( queryset=Region.objects.all(), field_name='site__region', @@ -444,7 +444,7 @@ class RackFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSe ) -class RackReservationFilterSet(NetBoxModelFilterSet, TenancyFilterSet): +class RackReservationFilterSet(PrimaryModelFilterSet, TenancyFilterSet): rack_id = django_filters.ModelMultipleChoiceFilter( queryset=Rack.objects.all(), label=_('Rack (ID)'), @@ -540,7 +540,7 @@ class ManufacturerFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet) fields = ('id', 'name', 'slug', 'description') -class DeviceTypeFilterSet(NetBoxModelFilterSet): +class DeviceTypeFilterSet(PrimaryModelFilterSet): manufacturer_id = django_filters.ModelMultipleChoiceFilter( queryset=Manufacturer.objects.all(), label=_('Manufacturer (ID)'), @@ -682,7 +682,7 @@ class DeviceTypeFilterSet(NetBoxModelFilterSet): return queryset.exclude(inventoryitemtemplates__isnull=value) -class ModuleTypeProfileFilterSet(NetBoxModelFilterSet): +class ModuleTypeProfileFilterSet(PrimaryModelFilterSet): class Meta: model = ModuleTypeProfile @@ -698,7 +698,7 @@ class ModuleTypeProfileFilterSet(NetBoxModelFilterSet): ) -class ModuleTypeFilterSet(AttributeFiltersMixin, NetBoxModelFilterSet): +class ModuleTypeFilterSet(AttributeFiltersMixin, PrimaryModelFilterSet): profile_id = django_filters.ModelMultipleChoiceFilter( queryset=ModuleTypeProfile.objects.all(), label=_('Profile (ID)'), @@ -1043,7 +1043,7 @@ class PlatformFilterSet(OrganizationalModelFilterSet): class DeviceFilterSet( - NetBoxModelFilterSet, + PrimaryModelFilterSet, TenancyFilterSet, ContactModelFilterSet, LocalConfigContextFilterSet, @@ -1345,7 +1345,7 @@ class DeviceFilterSet( return queryset.exclude(params) -class VirtualDeviceContextFilterSet(NetBoxModelFilterSet, TenancyFilterSet, PrimaryIPFilterSet): +class VirtualDeviceContextFilterSet(PrimaryModelFilterSet, TenancyFilterSet, PrimaryIPFilterSet): device_id = django_filters.ModelMultipleChoiceFilter( field_name='device', queryset=Device.objects.all(), @@ -1394,7 +1394,7 @@ class VirtualDeviceContextFilterSet(NetBoxModelFilterSet, TenancyFilterSet, Prim return queryset.exclude(params) -class ModuleFilterSet(NetBoxModelFilterSet): +class ModuleFilterSet(PrimaryModelFilterSet): manufacturer_id = django_filters.ModelMultipleChoiceFilter( field_name='module_type__manufacturer', queryset=Manufacturer.objects.all(), @@ -1516,7 +1516,7 @@ class ModuleFilterSet(NetBoxModelFilterSet): ).distinct() -class DeviceComponentFilterSet(django_filters.FilterSet): +class DeviceComponentFilterSet(PrimaryModelFilterSet): q = django_filters.CharFilter( method='search', label=_('Search'), @@ -1682,12 +1682,7 @@ class PathEndpointFilterSet(django_filters.FilterSet): return queryset.filter(Q(_path__isnull=True) | Q(_path__is_active=False)) -class ConsolePortFilterSet( - ModularDeviceComponentFilterSet, - NetBoxModelFilterSet, - CabledObjectFilterSet, - PathEndpointFilterSet -): +class ConsolePortFilterSet(ModularDeviceComponentFilterSet, CabledObjectFilterSet, PathEndpointFilterSet): type = django_filters.MultipleChoiceFilter( choices=ConsolePortTypeChoices, null_value=None @@ -1698,12 +1693,7 @@ class ConsolePortFilterSet( fields = ('id', 'name', 'label', 'speed', 'description', 'mark_connected', 'cable_end') -class ConsoleServerPortFilterSet( - ModularDeviceComponentFilterSet, - NetBoxModelFilterSet, - CabledObjectFilterSet, - PathEndpointFilterSet -): +class ConsoleServerPortFilterSet(ModularDeviceComponentFilterSet, CabledObjectFilterSet, PathEndpointFilterSet): type = django_filters.MultipleChoiceFilter( choices=ConsolePortTypeChoices, null_value=None @@ -1714,12 +1704,7 @@ class ConsoleServerPortFilterSet( fields = ('id', 'name', 'label', 'speed', 'description', 'mark_connected', 'cable_end') -class PowerPortFilterSet( - ModularDeviceComponentFilterSet, - NetBoxModelFilterSet, - CabledObjectFilterSet, - PathEndpointFilterSet -): +class PowerPortFilterSet(ModularDeviceComponentFilterSet, CabledObjectFilterSet, PathEndpointFilterSet): type = django_filters.MultipleChoiceFilter( choices=PowerPortTypeChoices, null_value=None @@ -1732,12 +1717,7 @@ class PowerPortFilterSet( ) -class PowerOutletFilterSet( - ModularDeviceComponentFilterSet, - NetBoxModelFilterSet, - CabledObjectFilterSet, - PathEndpointFilterSet -): +class PowerOutletFilterSet(ModularDeviceComponentFilterSet, CabledObjectFilterSet, PathEndpointFilterSet): type = django_filters.MultipleChoiceFilter( choices=PowerOutletTypeChoices, null_value=None @@ -1762,7 +1742,7 @@ class PowerOutletFilterSet( ) -class MACAddressFilterSet(NetBoxModelFilterSet): +class MACAddressFilterSet(PrimaryModelFilterSet): mac_address = MultiValueMACAddressFilter() assigned_object_type = ContentTypeFilter() device = MultiValueCharFilter( @@ -1914,7 +1894,6 @@ class CommonInterfaceFilterSet(django_filters.FilterSet): class InterfaceFilterSet( ModularDeviceComponentFilterSet, - NetBoxModelFilterSet, CabledObjectFilterSet, PathEndpointFilterSet, CommonInterfaceFilterSet @@ -2075,11 +2054,7 @@ class InterfaceFilterSet( ) -class FrontPortFilterSet( - ModularDeviceComponentFilterSet, - NetBoxModelFilterSet, - CabledObjectFilterSet -): +class FrontPortFilterSet(ModularDeviceComponentFilterSet, CabledObjectFilterSet): type = django_filters.MultipleChoiceFilter( choices=PortTypeChoices, null_value=None @@ -2095,11 +2070,7 @@ class FrontPortFilterSet( ) -class RearPortFilterSet( - ModularDeviceComponentFilterSet, - NetBoxModelFilterSet, - CabledObjectFilterSet -): +class RearPortFilterSet(ModularDeviceComponentFilterSet, CabledObjectFilterSet): type = django_filters.MultipleChoiceFilter( choices=PortTypeChoices, null_value=None @@ -2112,7 +2083,7 @@ class RearPortFilterSet( ) -class ModuleBayFilterSet(ModularDeviceComponentFilterSet, NetBoxModelFilterSet): +class ModuleBayFilterSet(ModularDeviceComponentFilterSet): parent_id = django_filters.ModelMultipleChoiceFilter( queryset=ModuleBay.objects.all(), label=_('Parent module bay (ID)'), @@ -2128,7 +2099,7 @@ class ModuleBayFilterSet(ModularDeviceComponentFilterSet, NetBoxModelFilterSet): fields = ('id', 'name', 'label', 'position', 'description') -class DeviceBayFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet): +class DeviceBayFilterSet(DeviceComponentFilterSet): installed_device_id = django_filters.ModelMultipleChoiceFilter( queryset=Device.objects.all(), label=_('Installed device (ID)'), @@ -2145,7 +2116,7 @@ class DeviceBayFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet): fields = ('id', 'name', 'label', 'description') -class InventoryItemFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet): +class InventoryItemFilterSet(DeviceComponentFilterSet): parent_id = django_filters.ModelMultipleChoiceFilter( queryset=InventoryItem.objects.all(), label=_('Parent inventory item (ID)'), @@ -2204,7 +2175,7 @@ class InventoryItemRoleFilterSet(OrganizationalModelFilterSet): fields = ('id', 'name', 'slug', 'color', 'description') -class VirtualChassisFilterSet(NetBoxModelFilterSet): +class VirtualChassisFilterSet(PrimaryModelFilterSet): master_id = django_filters.ModelMultipleChoiceFilter( queryset=Device.objects.all(), label=_('Master (ID)'), @@ -2280,7 +2251,7 @@ class VirtualChassisFilterSet(NetBoxModelFilterSet): return queryset.filter(qs_filter).distinct() -class CableFilterSet(TenancyFilterSet, NetBoxModelFilterSet): +class CableFilterSet(TenancyFilterSet, PrimaryModelFilterSet): termination_a_type = ContentTypeFilter( field_name='terminations__termination_type' ) @@ -2457,7 +2428,7 @@ class CableTerminationFilterSet(ChangeLoggedModelFilterSet): fields = ('id', 'cable', 'cable_end', 'termination_type', 'termination_id') -class PowerPanelFilterSet(NetBoxModelFilterSet, ContactModelFilterSet): +class PowerPanelFilterSet(PrimaryModelFilterSet, ContactModelFilterSet): region_id = TreeNodeMultipleChoiceFilter( queryset=Region.objects.all(), field_name='site__region', @@ -2515,7 +2486,7 @@ class PowerPanelFilterSet(NetBoxModelFilterSet, ContactModelFilterSet): return queryset.filter(qs_filter) -class PowerFeedFilterSet(NetBoxModelFilterSet, CabledObjectFilterSet, PathEndpointFilterSet, TenancyFilterSet): +class PowerFeedFilterSet(PrimaryModelFilterSet, CabledObjectFilterSet, PathEndpointFilterSet, TenancyFilterSet): region_id = TreeNodeMultipleChoiceFilter( queryset=Region.objects.all(), field_name='power_panel__site__region', diff --git a/netbox/extras/filtersets.py b/netbox/extras/filtersets.py index f34b21370..c4e3502c0 100644 --- a/netbox/extras/filtersets.py +++ b/netbox/extras/filtersets.py @@ -7,6 +7,7 @@ from core.models import DataSource, ObjectType from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup from netbox.filtersets import BaseFilterSet, ChangeLoggedModelFilterSet, NetBoxModelFilterSet from tenancy.models import Tenant, TenantGroup +from users.filterset_mixins import OwnerFilterMixin from users.models import Group, User from utilities.filters import ( ContentTypeFilter, MultiValueCharFilter, MultiValueNumberFilter @@ -619,7 +620,7 @@ class ConfigContextProfileFilterSet(NetBoxModelFilterSet): ) -class ConfigContextFilterSet(ChangeLoggedModelFilterSet): +class ConfigContextFilterSet(OwnerFilterMixin, ChangeLoggedModelFilterSet): q = django_filters.CharFilter( method='search', label=_('Search'), diff --git a/netbox/ipam/filtersets.py b/netbox/ipam/filtersets.py index 1e2ed91ed..3b738e5a7 100644 --- a/netbox/ipam/filtersets.py +++ b/netbox/ipam/filtersets.py @@ -11,7 +11,9 @@ from netaddr.core import AddrFormatError from circuits.models import Provider from dcim.models import Device, Interface, Region, Site, SiteGroup -from netbox.filtersets import ChangeLoggedModelFilterSet, OrganizationalModelFilterSet, NetBoxModelFilterSet +from netbox.filtersets import ( + ChangeLoggedModelFilterSet, OrganizationalModelFilterSet, NetBoxModelFilterSet, PrimaryModelFilterSet, +) from tenancy.filtersets import ContactModelFilterSet, TenancyFilterSet from utilities.filters import ( @@ -45,7 +47,7 @@ __all__ = ( ) -class VRFFilterSet(NetBoxModelFilterSet, TenancyFilterSet): +class VRFFilterSet(PrimaryModelFilterSet, TenancyFilterSet): import_target_id = django_filters.ModelMultipleChoiceFilter( field_name='import_targets', queryset=RouteTarget.objects.all(), @@ -83,7 +85,7 @@ class VRFFilterSet(NetBoxModelFilterSet, TenancyFilterSet): fields = ('id', 'name', 'rd', 'enforce_unique', 'description') -class RouteTargetFilterSet(NetBoxModelFilterSet, TenancyFilterSet): +class RouteTargetFilterSet(PrimaryModelFilterSet, TenancyFilterSet): importing_vrf_id = django_filters.ModelMultipleChoiceFilter( field_name='importing_vrfs', queryset=VRF.objects.all(), @@ -149,7 +151,7 @@ class RIRFilterSet(OrganizationalModelFilterSet): fields = ('id', 'name', 'slug', 'is_private', 'description') -class AggregateFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet): +class AggregateFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ContactModelFilterSet): family = django_filters.NumberFilter( field_name='prefix', lookup_expr='family' @@ -221,7 +223,7 @@ class ASNRangeFilterSet(OrganizationalModelFilterSet, TenancyFilterSet): ) -class ASNFilterSet(OrganizationalModelFilterSet, TenancyFilterSet): +class ASNFilterSet(PrimaryModelFilterSet, TenancyFilterSet): rir_id = django_filters.ModelMultipleChoiceFilter( queryset=RIR.objects.all(), label=_('RIR (ID)'), @@ -290,7 +292,7 @@ class RoleFilterSet(OrganizationalModelFilterSet): fields = ('id', 'name', 'slug', 'description', 'weight') -class PrefixFilterSet(NetBoxModelFilterSet, ScopedFilterSet, TenancyFilterSet, ContactModelFilterSet): +class PrefixFilterSet(PrimaryModelFilterSet, ScopedFilterSet, TenancyFilterSet, ContactModelFilterSet): family = django_filters.NumberFilter( field_name='prefix', lookup_expr='family' @@ -456,7 +458,7 @@ class PrefixFilterSet(NetBoxModelFilterSet, ScopedFilterSet, TenancyFilterSet, C ).distinct() -class IPRangeFilterSet(TenancyFilterSet, NetBoxModelFilterSet, ContactModelFilterSet): +class IPRangeFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ContactModelFilterSet): family = django_filters.NumberFilter( field_name='start_address', lookup_expr='family' @@ -548,7 +550,7 @@ class IPRangeFilterSet(TenancyFilterSet, NetBoxModelFilterSet, ContactModelFilte return queryset.filter(q) -class IPAddressFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet): +class IPAddressFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ContactModelFilterSet): family = django_filters.NumberFilter( field_name='address', lookup_expr='family' @@ -784,7 +786,7 @@ class IPAddressFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFil ) -class FHRPGroupFilterSet(NetBoxModelFilterSet): +class FHRPGroupFilterSet(PrimaryModelFilterSet): protocol = django_filters.MultipleChoiceFilter( choices=FHRPGroupProtocolChoices ) @@ -934,7 +936,7 @@ class VLANGroupFilterSet(OrganizationalModelFilterSet, TenancyFilterSet): ) -class VLANFilterSet(NetBoxModelFilterSet, TenancyFilterSet): +class VLANFilterSet(PrimaryModelFilterSet, TenancyFilterSet): region_id = TreeNodeMultipleChoiceFilter( queryset=Region.objects.all(), field_name='site__region', @@ -1085,7 +1087,7 @@ class VLANFilterSet(NetBoxModelFilterSet, TenancyFilterSet): ).distinct() -class VLANTranslationPolicyFilterSet(NetBoxModelFilterSet): +class VLANTranslationPolicyFilterSet(PrimaryModelFilterSet): class Meta: model = VLANTranslationPolicy @@ -1132,7 +1134,7 @@ class VLANTranslationRuleFilterSet(NetBoxModelFilterSet): return queryset.filter(qs_filter) -class ServiceTemplateFilterSet(NetBoxModelFilterSet): +class ServiceTemplateFilterSet(PrimaryModelFilterSet): port = NumericArrayFilter( field_name='ports', lookup_expr='contains' @@ -1152,7 +1154,7 @@ class ServiceTemplateFilterSet(NetBoxModelFilterSet): return queryset.filter(qs_filter) -class ServiceFilterSet(ContactModelFilterSet, NetBoxModelFilterSet): +class ServiceFilterSet(ContactModelFilterSet, PrimaryModelFilterSet): parent_object_type = ContentTypeFilter() device = MultiValueCharFilter( method='filter_device', diff --git a/netbox/netbox/filtersets.py b/netbox/netbox/filtersets.py index ea24efe48..24405cb6c 100644 --- a/netbox/netbox/filtersets.py +++ b/netbox/netbox/filtersets.py @@ -14,6 +14,7 @@ from core.models import ObjectChange from extras.choices import CustomFieldFilterLogicChoices from extras.filters import TagFilter, TagIDFilter from extras.models import CustomField, SavedFilter +from users.filterset_mixins import OwnerFilterMixin from utilities.constants import ( FILTER_CHAR_BASED_LOOKUP_MAP, FILTER_NEGATION_LOOKUP_MAP, FILTER_TREENODE_NEGATION_LOOKUP_MAP, FILTER_NUMERIC_BASED_LOOKUP_MAP @@ -25,8 +26,10 @@ __all__ = ( 'AttributeFiltersMixin', 'BaseFilterSet', 'ChangeLoggedModelFilterSet', + 'NestedGroupModelFilterSet', 'NetBoxModelFilterSet', 'OrganizationalModelFilterSet', + 'PrimaryModelFilterSet', ) STANDARD_LOOKUPS = ( @@ -328,9 +331,16 @@ class NetBoxModelFilterSet(ChangeLoggedModelFilterSet): return queryset -class OrganizationalModelFilterSet(NetBoxModelFilterSet): +class PrimaryModelFilterSet(OwnerFilterMixin, NetBoxModelFilterSet): """ - A base class for adding the search method to models which only expose the `name` and `slug` fields + Base filterset for models inheriting from PrimaryModel. + """ + pass + + +class OrganizationalModelFilterSet(OwnerFilterMixin, NetBoxModelFilterSet): + """ + Base filterset for models inheriting from OrganizationalModel. """ def search(self, queryset, name, value): if not value.strip(): @@ -342,9 +352,9 @@ class OrganizationalModelFilterSet(NetBoxModelFilterSet): ) -class NestedGroupModelFilterSet(NetBoxModelFilterSet): +class NestedGroupModelFilterSet(OwnerFilterMixin, NetBoxModelFilterSet): """ - A base FilterSet for models that inherit from NestedGroupModel + Base filterset for models inheriting from NestedGroupModel. """ def search(self, queryset, name, value): if value.strip(): diff --git a/netbox/tenancy/filtersets.py b/netbox/tenancy/filtersets.py index ca0142db6..b650ea882 100644 --- a/netbox/tenancy/filtersets.py +++ b/netbox/tenancy/filtersets.py @@ -2,7 +2,9 @@ import django_filters from django.db.models import Q from django.utils.translation import gettext as _ -from netbox.filtersets import NestedGroupModelFilterSet, NetBoxModelFilterSet, OrganizationalModelFilterSet +from netbox.filtersets import ( + NestedGroupModelFilterSet, NetBoxModelFilterSet, OrganizationalModelFilterSet, PrimaryModelFilterSet, +) from utilities.filters import ContentTypeFilter, TreeNodeMultipleChoiceFilter from .models import * @@ -64,7 +66,7 @@ class ContactRoleFilterSet(OrganizationalModelFilterSet): fields = ('id', 'name', 'slug', 'description') -class ContactFilterSet(NetBoxModelFilterSet): +class ContactFilterSet(PrimaryModelFilterSet): group_id = TreeNodeMultipleChoiceFilter( queryset=ContactGroup.objects.all(), field_name='groups', @@ -198,7 +200,7 @@ class TenantGroupFilterSet(NestedGroupModelFilterSet): fields = ('id', 'name', 'slug', 'description') -class TenantFilterSet(NetBoxModelFilterSet, ContactModelFilterSet): +class TenantFilterSet(PrimaryModelFilterSet, ContactModelFilterSet): group_id = TreeNodeMultipleChoiceFilter( queryset=TenantGroup.objects.all(), field_name='group', diff --git a/netbox/users/filterset_mixins.py b/netbox/users/filterset_mixins.py new file mode 100644 index 000000000..33eb6f743 --- /dev/null +++ b/netbox/users/filterset_mixins.py @@ -0,0 +1,24 @@ +import django_filters +from django.utils.translation import gettext as _ + +from users.models import Owner + +__all__ = ( + 'OwnerFilterMixin', +) + + +class OwnerFilterMixin(django_filters.FilterSet): + """ + Adds owner & owner_id filters for models which inherit from OwnerMixin. + """ + owner_id = django_filters.ModelMultipleChoiceFilter( + queryset=Owner.objects.all(), + label=_('Owner (ID)'), + ) + owner = django_filters.ModelMultipleChoiceFilter( + field_name='owner__name', + queryset=Owner.objects.all(), + to_field_name='name', + label=_('Owner (name)'), + ) diff --git a/netbox/virtualization/filtersets.py b/netbox/virtualization/filtersets.py index 802e34e00..567b20b6d 100644 --- a/netbox/virtualization/filtersets.py +++ b/netbox/virtualization/filtersets.py @@ -9,7 +9,7 @@ from dcim.models import MACAddress from extras.filtersets import LocalConfigContextFilterSet from extras.models import ConfigTemplate from ipam.filtersets import PrimaryIPFilterSet -from netbox.filtersets import OrganizationalModelFilterSet, NetBoxModelFilterSet +from netbox.filtersets import OrganizationalModelFilterSet, PrimaryModelFilterSet from tenancy.filtersets import TenancyFilterSet, ContactModelFilterSet from utilities.filters import MultiValueCharFilter, MultiValueMACAddressFilter, TreeNodeMultipleChoiceFilter from .choices import * @@ -39,7 +39,7 @@ class ClusterGroupFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet) fields = ('id', 'name', 'slug', 'description') -class ClusterFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ScopedFilterSet, ContactModelFilterSet): +class ClusterFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ScopedFilterSet, ContactModelFilterSet): group_id = django_filters.ModelMultipleChoiceFilter( queryset=ClusterGroup.objects.all(), label=_('Parent group (ID)'), @@ -80,7 +80,7 @@ class ClusterFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ScopedFilterSet, class VirtualMachineFilterSet( - NetBoxModelFilterSet, + PrimaryModelFilterSet, TenancyFilterSet, ContactModelFilterSet, LocalConfigContextFilterSet, @@ -235,7 +235,7 @@ class VirtualMachineFilterSet( return queryset.exclude(params) -class VMInterfaceFilterSet(NetBoxModelFilterSet, CommonInterfaceFilterSet): +class VMInterfaceFilterSet(PrimaryModelFilterSet, CommonInterfaceFilterSet): cluster_id = django_filters.ModelMultipleChoiceFilter( field_name='virtual_machine__cluster', queryset=Cluster.objects.all(), @@ -297,7 +297,7 @@ class VMInterfaceFilterSet(NetBoxModelFilterSet, CommonInterfaceFilterSet): ) -class VirtualDiskFilterSet(NetBoxModelFilterSet): +class VirtualDiskFilterSet(PrimaryModelFilterSet): virtual_machine_id = django_filters.ModelMultipleChoiceFilter( field_name='virtual_machine', queryset=VirtualMachine.objects.all(), diff --git a/netbox/vpn/filtersets.py b/netbox/vpn/filtersets.py index d35831e2f..9010c5e2c 100644 --- a/netbox/vpn/filtersets.py +++ b/netbox/vpn/filtersets.py @@ -4,7 +4,7 @@ from django.utils.translation import gettext as _ from dcim.models import Device, Interface from ipam.models import IPAddress, RouteTarget, VLAN -from netbox.filtersets import NetBoxModelFilterSet, OrganizationalModelFilterSet +from netbox.filtersets import NetBoxModelFilterSet, OrganizationalModelFilterSet, PrimaryModelFilterSet from tenancy.filtersets import ContactModelFilterSet, TenancyFilterSet from utilities.filters import ContentTypeFilter, MultiValueCharFilter, MultiValueNumberFilter from virtualization.models import VirtualMachine, VMInterface @@ -32,7 +32,7 @@ class TunnelGroupFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet): fields = ('id', 'name', 'slug', 'description') -class TunnelFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet): +class TunnelFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ContactModelFilterSet): status = django_filters.MultipleChoiceFilter( choices=TunnelStatusChoices ) @@ -123,7 +123,7 @@ class TunnelTerminationFilterSet(NetBoxModelFilterSet): fields = ('id', 'termination_id') -class IKEProposalFilterSet(NetBoxModelFilterSet): +class IKEProposalFilterSet(PrimaryModelFilterSet): ike_policy_id = django_filters.ModelMultipleChoiceFilter( field_name='ike_policies', queryset=IKEPolicy.objects.all(), @@ -162,7 +162,7 @@ class IKEProposalFilterSet(NetBoxModelFilterSet): ) -class IKEPolicyFilterSet(NetBoxModelFilterSet): +class IKEPolicyFilterSet(PrimaryModelFilterSet): version = django_filters.MultipleChoiceFilter( choices=IKEVersionChoices ) @@ -193,7 +193,7 @@ class IKEPolicyFilterSet(NetBoxModelFilterSet): ) -class IPSecProposalFilterSet(NetBoxModelFilterSet): +class IPSecProposalFilterSet(PrimaryModelFilterSet): ipsec_policy_id = django_filters.ModelMultipleChoiceFilter( field_name='ipsec_policies', queryset=IPSecPolicy.objects.all(), @@ -226,7 +226,7 @@ class IPSecProposalFilterSet(NetBoxModelFilterSet): ) -class IPSecPolicyFilterSet(NetBoxModelFilterSet): +class IPSecPolicyFilterSet(PrimaryModelFilterSet): pfs_group = django_filters.MultipleChoiceFilter( choices=DHGroupChoices ) @@ -254,7 +254,7 @@ class IPSecPolicyFilterSet(NetBoxModelFilterSet): ) -class IPSecProfileFilterSet(NetBoxModelFilterSet): +class IPSecProfileFilterSet(PrimaryModelFilterSet): mode = django_filters.MultipleChoiceFilter( choices=IPSecModeChoices ) @@ -293,7 +293,7 @@ class IPSecProfileFilterSet(NetBoxModelFilterSet): ) -class L2VPNFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet): +class L2VPNFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ContactModelFilterSet): type = django_filters.MultipleChoiceFilter( choices=L2VPNTypeChoices, null_value=None diff --git a/netbox/wireless/filtersets.py b/netbox/wireless/filtersets.py index bd96865ad..afd963a5a 100644 --- a/netbox/wireless/filtersets.py +++ b/netbox/wireless/filtersets.py @@ -5,7 +5,7 @@ from dcim.choices import LinkStatusChoices from dcim.base_filtersets import ScopedFilterSet from dcim.models import Interface from ipam.models import VLAN -from netbox.filtersets import NestedGroupModelFilterSet, NetBoxModelFilterSet +from netbox.filtersets import NestedGroupModelFilterSet, PrimaryModelFilterSet from tenancy.filtersets import TenancyFilterSet from utilities.filters import TreeNodeMultipleChoiceFilter from .choices import * @@ -44,7 +44,7 @@ class WirelessLANGroupFilterSet(NestedGroupModelFilterSet): fields = ('id', 'name', 'slug', 'description') -class WirelessLANFilterSet(NetBoxModelFilterSet, ScopedFilterSet, TenancyFilterSet): +class WirelessLANFilterSet(PrimaryModelFilterSet, ScopedFilterSet, TenancyFilterSet): group_id = TreeNodeMultipleChoiceFilter( queryset=WirelessLANGroup.objects.all(), field_name='group', @@ -87,7 +87,7 @@ class WirelessLANFilterSet(NetBoxModelFilterSet, ScopedFilterSet, TenancyFilterS return queryset.filter(qs_filter) -class WirelessLinkFilterSet(NetBoxModelFilterSet, TenancyFilterSet): +class WirelessLinkFilterSet(PrimaryModelFilterSet, TenancyFilterSet): interface_a_id = django_filters.ModelMultipleChoiceFilter( queryset=Interface.objects.all() )