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

#9623: Add slug field to SavedFilter

This commit is contained in:
jeremystretch
2022-11-15 10:44:12 -05:00
parent ecf5304a14
commit 355678274d
22 changed files with 121 additions and 82 deletions

View File

@ -20,7 +20,7 @@ __all__ = (
class ProviderFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
model = Provider
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Location', ('region_id', 'site_group_id', 'site_id')),
('ASN', ('asn',)),
('Contacts', ('contact', 'contact_role', 'contact_group')),
@ -59,7 +59,7 @@ class ProviderFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
class ProviderNetworkFilterForm(NetBoxModelFilterSetForm):
model = ProviderNetwork
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('provider_id', 'service_id')),
)
provider_id = DynamicModelMultipleChoiceField(
@ -82,7 +82,7 @@ class CircuitTypeFilterForm(NetBoxModelFilterSetForm):
class CircuitFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilterSetForm):
model = Circuit
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Provider', ('provider_id', 'provider_network_id')),
('Attributes', ('type_id', 'status', 'install_date', 'termination_date', 'commit_rate')),
('Location', ('region_id', 'site_group_id', 'site_id')),

View File

@ -117,7 +117,7 @@ class DeviceComponentFilterForm(NetBoxModelFilterSetForm):
class RegionFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
model = Region
fieldsets = (
(None, ('q', 'filter', 'tag', 'parent_id')),
(None, ('q', 'filter_id', 'tag', 'parent_id')),
('Contacts', ('contact', 'contact_role', 'contact_group'))
)
parent_id = DynamicModelMultipleChoiceField(
@ -131,7 +131,7 @@ class RegionFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
class SiteGroupFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
model = SiteGroup
fieldsets = (
(None, ('q', 'filter', 'tag', 'parent_id')),
(None, ('q', 'filter_id', 'tag', 'parent_id')),
('Contacts', ('contact', 'contact_role', 'contact_group'))
)
parent_id = DynamicModelMultipleChoiceField(
@ -145,7 +145,7 @@ class SiteGroupFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
class SiteFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilterSetForm):
model = Site
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('status', 'region_id', 'group_id', 'asn_id')),
('Tenant', ('tenant_group_id', 'tenant_id')),
('Contacts', ('contact', 'contact_role', 'contact_group')),
@ -175,7 +175,7 @@ class SiteFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilte
class LocationFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilterSetForm):
model = Location
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('region_id', 'site_group_id', 'site_id', 'parent_id', 'status')),
('Tenant', ('tenant_group_id', 'tenant_id')),
('Contacts', ('contact', 'contact_role', 'contact_group')),
@ -223,7 +223,7 @@ class RackRoleFilterForm(NetBoxModelFilterSetForm):
class RackFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilterSetForm):
model = Rack
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Location', ('region_id', 'site_group_id', 'site_id', 'location_id')),
('Function', ('status', 'role_id')),
('Hardware', ('type', 'width', 'serial', 'asset_tag')),
@ -307,7 +307,7 @@ class RackElevationFilterForm(RackFilterForm):
class RackReservationFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = RackReservation
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('User', ('user_id',)),
('Rack', ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')),
('Tenant', ('tenant_group_id', 'tenant_id')),
@ -363,7 +363,7 @@ class RackReservationFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
class ManufacturerFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
model = Manufacturer
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Contacts', ('contact', 'contact_role', 'contact_group'))
)
tag = TagFilterField(model)
@ -372,7 +372,7 @@ class ManufacturerFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
class DeviceTypeFilterForm(NetBoxModelFilterSetForm):
model = DeviceType
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Hardware', ('manufacturer_id', 'part_number', 'subdevice_role', 'airflow')),
('Images', ('has_front_image', 'has_rear_image')),
('Components', (
@ -487,7 +487,7 @@ class DeviceTypeFilterForm(NetBoxModelFilterSetForm):
class ModuleTypeFilterForm(NetBoxModelFilterSetForm):
model = ModuleType
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Hardware', ('manufacturer_id', 'part_number')),
('Components', (
'console_ports', 'console_server_ports', 'power_ports', 'power_outlets', 'interfaces',
@ -579,7 +579,7 @@ class DeviceFilterForm(
):
model = Device
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Location', ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')),
('Operation', ('status', 'role_id', 'airflow', 'serial', 'asset_tag', 'mac_address')),
('Hardware', ('manufacturer_id', 'device_type_id', 'platform_id')),
@ -735,7 +735,7 @@ class VirtualDeviceContextFilterForm(
):
model = VirtualDeviceContext
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Hardware', ('device', 'status', )),
('Tenant', ('tenant_group_id', 'tenant_id')),
('Miscellaneous', ('has_primary_ip',))
@ -763,7 +763,7 @@ class VirtualDeviceContextFilterForm(
class ModuleFilterForm(LocalConfigContextFilterForm, TenancyFilterForm, NetBoxModelFilterSetForm):
model = Module
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Hardware', ('manufacturer_id', 'module_type_id', 'serial', 'asset_tag')),
)
manufacturer_id = DynamicModelMultipleChoiceField(
@ -793,7 +793,7 @@ class ModuleFilterForm(LocalConfigContextFilterForm, TenancyFilterForm, NetBoxMo
class VirtualChassisFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = VirtualChassis
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Location', ('region_id', 'site_group_id', 'site_id')),
('Tenant', ('tenant_group_id', 'tenant_id')),
)
@ -822,7 +822,7 @@ class VirtualChassisFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
class CableFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = Cable
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Location', ('site_id', 'location_id', 'rack_id', 'device_id')),
('Attributes', ('type', 'status', 'color', 'length', 'length_unit')),
('Tenant', ('tenant_group_id', 'tenant_id')),
@ -894,7 +894,7 @@ class CableFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
class PowerPanelFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
model = PowerPanel
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Location', ('region_id', 'site_group_id', 'site_id', 'location_id')),
('Contacts', ('contact', 'contact_role', 'contact_group')),
)
@ -932,7 +932,7 @@ class PowerPanelFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
class PowerFeedFilterForm(NetBoxModelFilterSetForm):
model = PowerFeed
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Location', ('region_id', 'site_group_id', 'site_id', 'power_panel_id', 'rack_id')),
('Attributes', ('status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization')),
)
@ -1034,7 +1034,7 @@ class PathEndpointFilterForm(CabledFilterForm):
class ConsolePortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
model = ConsolePort
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('name', 'label', 'type', 'speed')),
('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', 'virtual_chassis_id', 'device_id')),
('Connection', ('cabled', 'connected', 'occupied')),
@ -1053,7 +1053,7 @@ class ConsolePortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
class ConsoleServerPortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
model = ConsoleServerPort
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('name', 'label', 'type', 'speed')),
('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', 'virtual_chassis_id', 'device_id')),
('Connection', ('cabled', 'connected', 'occupied')),
@ -1072,7 +1072,7 @@ class ConsoleServerPortFilterForm(PathEndpointFilterForm, DeviceComponentFilterF
class PowerPortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
model = PowerPort
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('name', 'label', 'type')),
('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', 'virtual_chassis_id', 'device_id')),
('Connection', ('cabled', 'connected', 'occupied')),
@ -1087,7 +1087,7 @@ class PowerPortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
class PowerOutletFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
model = PowerOutlet
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('name', 'label', 'type')),
('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', 'virtual_chassis_id', 'device_id')),
('Connection', ('cabled', 'connected', 'occupied')),
@ -1102,7 +1102,7 @@ class PowerOutletFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
class InterfaceFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
model = Interface
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('name', 'label', 'kind', 'type', 'speed', 'duplex', 'enabled', 'mgmt_only')),
('Addressing', ('vrf_id', 'mac_address', 'wwn')),
('PoE', ('poe_mode', 'poe_type')),
@ -1200,7 +1200,7 @@ class InterfaceFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
class FrontPortFilterForm(CabledFilterForm, DeviceComponentFilterForm):
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('name', 'label', 'type', 'color')),
('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', 'virtual_chassis_id', 'device_id')),
('Cable', ('cabled', 'occupied')),
@ -1219,7 +1219,7 @@ class FrontPortFilterForm(CabledFilterForm, DeviceComponentFilterForm):
class RearPortFilterForm(CabledFilterForm, DeviceComponentFilterForm):
model = RearPort
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('name', 'label', 'type', 'color')),
('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', 'virtual_chassis_id', 'device_id')),
('Cable', ('cabled', 'occupied')),
@ -1237,7 +1237,7 @@ class RearPortFilterForm(CabledFilterForm, DeviceComponentFilterForm):
class ModuleBayFilterForm(DeviceComponentFilterForm):
model = ModuleBay
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('name', 'label', 'position')),
('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', 'virtual_chassis_id', 'device_id')),
)
@ -1250,7 +1250,7 @@ class ModuleBayFilterForm(DeviceComponentFilterForm):
class DeviceBayFilterForm(DeviceComponentFilterForm):
model = DeviceBay
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('name', 'label')),
('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', 'virtual_chassis_id', 'device_id')),
)
@ -1260,7 +1260,7 @@ class DeviceBayFilterForm(DeviceComponentFilterForm):
class InventoryItemFilterForm(DeviceComponentFilterForm):
model = InventoryItem
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('name', 'label', 'role_id', 'manufacturer_id', 'serial', 'asset_tag', 'discovered')),
('Device', ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', 'virtual_chassis_id', 'device_id')),
)

View File

@ -64,7 +64,7 @@ class NestedSavedFilterSerializer(WritableNestedSerializer):
class Meta:
model = models.SavedFilter
fields = ['id', 'url', 'display', 'name']
fields = ['id', 'url', 'display', 'name', 'slug']
class NestedImageAttachmentSerializer(WritableNestedSerializer):

View File

@ -164,8 +164,8 @@ class SavedFilterSerializer(ValidatedModelSerializer):
class Meta:
model = SavedFilter
fields = [
'id', 'url', 'display', 'content_types', 'name', 'description', 'user', 'weight',
'enabled', 'shared', 'parameters', 'created', 'last_updated',
'id', 'url', 'display', 'content_types', 'name', 'slug', 'description', 'user', 'weight', 'enabled',
'shared', 'parameters', 'created', 'last_updated',
]

View File

@ -165,7 +165,7 @@ class SavedFilterFilterSet(BaseFilterSet):
class Meta:
model = SavedFilter
fields = ['id', 'content_types', 'name', 'description', 'enabled', 'shared', 'weight']
fields = ['id', 'content_types', 'name', 'slug', 'description', 'enabled', 'shared', 'weight']
def search(self, queryset, name, value):
if not value.strip():

View File

@ -92,7 +92,7 @@ class SavedFilterCSVForm(CSVModelForm):
class Meta:
model = SavedFilter
fields = (
'name', 'content_types', 'description', 'weight', 'enabled', 'shared', 'parameters',
'name', 'slug', 'content_types', 'description', 'weight', 'enabled', 'shared', 'parameters',
)

View File

@ -34,7 +34,7 @@ __all__ = (
class CustomFieldFilterForm(SavedFiltersMixin, FilterForm):
fieldsets = (
(None, ('q', 'filter')),
(None, ('q', 'filter_id')),
('Attributes', ('type', 'content_type_id', 'group_name', 'weight', 'required', 'ui_visibility')),
)
content_type_id = ContentTypeMultipleChoiceField(
@ -70,7 +70,7 @@ class CustomFieldFilterForm(SavedFiltersMixin, FilterForm):
class JobResultFilterForm(SavedFiltersMixin, FilterForm):
fieldsets = (
(None, ('q', 'filter')),
(None, ('q', 'filter_id')),
('Attributes', ('obj_type', 'status')),
('Creation', ('created__before', 'created__after', 'completed__before', 'completed__after',
'scheduled_time__before', 'scheduled_time__after', 'user')),
@ -122,7 +122,7 @@ class JobResultFilterForm(SavedFiltersMixin, FilterForm):
class CustomLinkFilterForm(SavedFiltersMixin, FilterForm):
fieldsets = (
(None, ('q', 'filter')),
(None, ('q', 'filter_id')),
('Attributes', ('content_types', 'enabled', 'new_window', 'weight')),
)
content_types = ContentTypeMultipleChoiceField(
@ -149,7 +149,7 @@ class CustomLinkFilterForm(SavedFiltersMixin, FilterForm):
class ExportTemplateFilterForm(SavedFiltersMixin, FilterForm):
fieldsets = (
(None, ('q', 'filter')),
(None, ('q', 'filter_id')),
('Attributes', ('content_types', 'mime_type', 'file_extension', 'as_attachment')),
)
content_types = ContentTypeMultipleChoiceField(
@ -174,7 +174,7 @@ class ExportTemplateFilterForm(SavedFiltersMixin, FilterForm):
class SavedFilterFilterForm(SavedFiltersMixin, FilterForm):
fieldsets = (
(None, ('q', 'filter')),
(None, ('q', 'filter_id')),
('Attributes', ('content_types', 'enabled', 'shared', 'weight')),
)
content_types = ContentTypeMultipleChoiceField(
@ -201,7 +201,7 @@ class SavedFilterFilterForm(SavedFiltersMixin, FilterForm):
class WebhookFilterForm(SavedFiltersMixin, FilterForm):
fieldsets = (
(None, ('q', 'filter')),
(None, ('q', 'filter_id')),
('Attributes', ('content_type_id', 'http_method', 'enabled')),
('Events', ('type_create', 'type_update', 'type_delete')),
)
@ -253,7 +253,7 @@ class TagFilterForm(SavedFiltersMixin, FilterForm):
class ConfigContextFilterForm(SavedFiltersMixin, FilterForm):
fieldsets = (
(None, ('q', 'filter', 'tag_id')),
(None, ('q', 'filter_id', 'tag_id')),
('Location', ('region_id', 'site_group_id', 'site_id', 'location_id')),
('Device', ('device_type_id', 'platform_id', 'role_id')),
('Cluster', ('cluster_type_id', 'cluster_group_id', 'cluster_id')),
@ -340,7 +340,7 @@ class LocalConfigContextFilterForm(forms.Form):
class JournalEntryFilterForm(NetBoxModelFilterSetForm):
model = JournalEntry
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Creation', ('created_before', 'created_after', 'created_by_id')),
('Attributes', ('assigned_object_type_id', 'kind'))
)
@ -381,7 +381,7 @@ class JournalEntryFilterForm(NetBoxModelFilterSetForm):
class ObjectChangeFilterForm(SavedFiltersMixin, FilterForm):
model = ObjectChange
fieldsets = (
(None, ('q', 'filter')),
(None, ('q', 'filter_id')),
('Time', ('time_before', 'time_after')),
('Attributes', ('action', 'user_id', 'changed_object_type_id')),
)

View File

@ -64,7 +64,7 @@ class CustomFieldsMixin:
class SavedFiltersMixin(forms.Form):
filter = DynamicModelMultipleChoiceField(
filter_id = DynamicModelMultipleChoiceField(
queryset=SavedFilter.objects.all(),
required=False,
label=_('Saved Filter'),

View File

@ -112,12 +112,13 @@ class ExportTemplateForm(BootstrapMixin, forms.ModelForm):
class SavedFilterForm(BootstrapMixin, forms.ModelForm):
slug = SlugField()
content_types = ContentTypeMultipleChoiceField(
queryset=ContentType.objects.all()
)
fieldsets = (
('Saved Filter', ('name', 'content_types', 'description', 'weight', 'enabled', 'shared')),
('Saved Filter', ('name', 'slug', 'content_types', 'description', 'weight', 'enabled', 'shared')),
('Parameters', ('parameters',)),
)

View File

@ -1,8 +1,6 @@
# Generated by Django 4.1.1 on 2022-10-27 18:18
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
@ -21,6 +19,7 @@ class Migration(migrations.Migration):
('created', models.DateTimeField(auto_now_add=True, null=True)),
('last_updated', models.DateTimeField(auto_now=True, null=True)),
('name', models.CharField(max_length=100, unique=True)),
('slug', models.SlugField(max_length=100, unique=True)),
('description', models.CharField(blank=True, max_length=200)),
('weight', models.PositiveSmallIntegerField(default=100)),
('enabled', models.BooleanField(default=True)),

View File

@ -365,6 +365,10 @@ class SavedFilter(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogge
max_length=100,
unique=True
)
slug = models.SlugField(
max_length=100,
unique=True
)
description = models.CharField(
max_length=200,
blank=True

View File

@ -100,7 +100,7 @@ class SavedFilterTable(NetBoxTable):
class Meta(NetBoxTable.Meta):
model = SavedFilter
fields = (
'pk', 'id', 'name', 'content_types', 'description', 'user', 'weight', 'enabled', 'shared',
'pk', 'id', 'name', 'slug', 'content_types', 'description', 'user', 'weight', 'enabled', 'shared',
'created', 'last_updated',
)
default_columns = (

View File

@ -192,11 +192,12 @@ class CustomLinkTest(APIViewTestCases.APIViewTestCase):
class SavedFilterTest(APIViewTestCases.APIViewTestCase):
model = SavedFilter
brief_fields = ['display', 'id', 'name', 'url']
brief_fields = ['display', 'id', 'name', 'slug', 'url']
create_data = [
{
'content_types': ['dcim.site'],
'name': 'Saved Filter 4',
'slug': 'saved-filter-4',
'weight': 100,
'enabled': True,
'shared': True,
@ -205,6 +206,7 @@ class SavedFilterTest(APIViewTestCases.APIViewTestCase):
{
'content_types': ['dcim.site'],
'name': 'Saved Filter 5',
'slug': 'saved-filter-5',
'weight': 200,
'enabled': True,
'shared': True,
@ -213,6 +215,7 @@ class SavedFilterTest(APIViewTestCases.APIViewTestCase):
{
'content_types': ['dcim.site'],
'name': 'Saved Filter 6',
'slug': 'saved-filter-6',
'weight': 300,
'enabled': True,
'shared': True,
@ -232,6 +235,7 @@ class SavedFilterTest(APIViewTestCases.APIViewTestCase):
saved_filters = (
SavedFilter(
name='Saved Filter 1',
slug='saved-filter-1',
weight=100,
enabled=True,
shared=True,
@ -239,6 +243,7 @@ class SavedFilterTest(APIViewTestCases.APIViewTestCase):
),
SavedFilter(
name='Saved Filter 2',
slug='saved-filter-2',
weight=200,
enabled=True,
shared=True,
@ -246,6 +251,7 @@ class SavedFilterTest(APIViewTestCases.APIViewTestCase):
),
SavedFilter(
name='Saved Filter 3',
slug='saved-filter-3',
weight=300,
enabled=True,
shared=True,

View File

@ -240,6 +240,7 @@ class SavedFilterTestCase(TestCase, BaseFilterSetTests):
saved_filters = (
SavedFilter(
name='Saved Filter 1',
slug='saved-filter-1',
user=users[0],
weight=100,
enabled=True,
@ -248,6 +249,7 @@ class SavedFilterTestCase(TestCase, BaseFilterSetTests):
),
SavedFilter(
name='Saved Filter 2',
slug='saved-filter-2',
user=users[1],
weight=200,
enabled=True,
@ -256,6 +258,7 @@ class SavedFilterTestCase(TestCase, BaseFilterSetTests):
),
SavedFilter(
name='Saved Filter 3',
slug='saved-filter-3',
user=users[2],
weight=300,
enabled=False,
@ -271,6 +274,10 @@ class SavedFilterTestCase(TestCase, BaseFilterSetTests):
params = {'name': ['Saved Filter 1', 'Saved Filter 2']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_slug(self):
params = {'slug': ['saved-filter-1', 'saved-filter-2']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_content_types(self):
params = {'content_types': 'dcim.site'}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)

View File

@ -122,9 +122,27 @@ class SavedFilterTestCase(ViewTestCases.PrimaryObjectViewTestCase):
User.objects.bulk_create(users)
saved_filters = (
SavedFilter(name='Saved Filter 1', user=users[0], weight=100, parameters={'status': ['active']}),
SavedFilter(name='Saved Filter 2', user=users[1], weight=200, parameters={'status': ['planned']}),
SavedFilter(name='Saved Filter 3', user=users[2], weight=300, parameters={'status': ['retired']}),
SavedFilter(
name='Saved Filter 1',
slug='saved-filter-1',
user=users[0],
weight=100,
parameters={'status': ['active']}
),
SavedFilter(
name='Saved Filter 2',
slug='saved-filter-2',
user=users[1],
weight=200,
parameters={'status': ['planned']}
),
SavedFilter(
name='Saved Filter 3',
slug='saved-filter-3',
user=users[2],
weight=300,
parameters={'status': ['retired']}
),
)
SavedFilter.objects.bulk_create(saved_filters)
for i, savedfilter in enumerate(saved_filters):
@ -132,6 +150,7 @@ class SavedFilterTestCase(ViewTestCases.PrimaryObjectViewTestCase):
cls.form_data = {
'name': 'Saved Filter X',
'slug': 'saved-filter-x',
'content_types': [site_ct.pk],
'description': 'Foo',
'weight': 1000,
@ -141,10 +160,10 @@ class SavedFilterTestCase(ViewTestCases.PrimaryObjectViewTestCase):
}
cls.csv_data = (
'name,content_types,weight,enabled,shared,parameters',
'Saved Filter 4,dcim.device,400,True,True,{"foo": "a"}',
'Saved Filter 5,dcim.device,500,True,True,{"foo": "b"}',
'Saved Filter 6,dcim.device,600,True,True,{"foo": "c"}',
'name,slug,content_types,weight,enabled,shared,parameters',
'Saved Filter 4,saved-filter-4,dcim.device,400,True,True,{"foo": "a"}',
'Saved Filter 5,saved-filter-5,dcim.device,500,True,True,{"foo": "b"}',
'Saved Filter 6,saved-filter-6,dcim.device,600,True,True,{"foo": "c"}',
)
cls.csv_update_data = (

View File

@ -45,7 +45,7 @@ IPADDRESS_MASK_LENGTH_CHOICES = add_blank_choice([
class VRFFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = VRF
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Route Targets', ('import_target_id', 'export_target_id')),
('Tenant', ('tenant_group_id', 'tenant_id')),
)
@ -65,7 +65,7 @@ class VRFFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
class RouteTargetFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = RouteTarget
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('VRF', ('importing_vrf_id', 'exporting_vrf_id')),
('Tenant', ('tenant_group_id', 'tenant_id')),
)
@ -97,7 +97,7 @@ class RIRFilterForm(NetBoxModelFilterSetForm):
class AggregateFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = Aggregate
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('family', 'rir_id')),
('Tenant', ('tenant_group_id', 'tenant_id')),
)
@ -118,7 +118,7 @@ class AggregateFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
class ASNFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = ASN
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Assignment', ('rir_id', 'site_id')),
('Tenant', ('tenant_group_id', 'tenant_id')),
)
@ -143,7 +143,7 @@ class RoleFilterForm(NetBoxModelFilterSetForm):
class PrefixFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = Prefix
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Addressing', ('within_include', 'family', 'status', 'role_id', 'mask_length', 'is_pool', 'mark_utilized')),
('VRF', ('vrf_id', 'present_in_vrf_id')),
('Location', ('region_id', 'site_group_id', 'site_id')),
@ -232,7 +232,7 @@ class PrefixFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
class IPRangeFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = IPRange
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attriubtes', ('family', 'vrf_id', 'status', 'role_id')),
('Tenant', ('tenant_group_id', 'tenant_id')),
)
@ -264,7 +264,7 @@ class IPRangeFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
class IPAddressFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = IPAddress
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('parent', 'family', 'status', 'role', 'mask_length', 'assigned_to_interface')),
('VRF', ('vrf_id', 'present_in_vrf_id')),
('Tenant', ('tenant_group_id', 'tenant_id')),
@ -333,7 +333,7 @@ class IPAddressFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
class FHRPGroupFilterForm(NetBoxModelFilterSetForm):
model = FHRPGroup
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('name', 'protocol', 'group_id')),
('Authentication', ('auth_type', 'auth_key')),
)
@ -363,7 +363,7 @@ class FHRPGroupFilterForm(NetBoxModelFilterSetForm):
class VLANGroupFilterForm(NetBoxModelFilterSetForm):
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Location', ('region', 'sitegroup', 'site', 'location', 'rack')),
('VLAN ID', ('min_vid', 'max_vid')),
)
@ -411,7 +411,7 @@ class VLANGroupFilterForm(NetBoxModelFilterSetForm):
class VLANFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = VLAN
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Location', ('region_id', 'site_group_id', 'site_id')),
('Attributes', ('group_id', 'status', 'role_id', 'vid')),
('Tenant', ('tenant_group_id', 'tenant_id')),
@ -464,7 +464,7 @@ class VLANFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
class ServiceTemplateFilterForm(NetBoxModelFilterSetForm):
model = ServiceTemplate
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('protocol', 'port')),
)
protocol = forms.ChoiceField(
@ -485,7 +485,7 @@ class ServiceFilterForm(ServiceTemplateFilterForm):
class L2VPNFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = L2VPN
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('type', 'import_target_id', 'export_target_id')),
('Tenant', ('tenant_group_id', 'tenant_id')),
)
@ -510,7 +510,7 @@ class L2VPNFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
class L2VPNTerminationFilterForm(NetBoxModelFilterSetForm):
model = L2VPNTermination
fieldsets = (
(None, ('filter', 'l2vpn_id',)),
(None, ('filter_id', 'l2vpn_id',)),
('Assigned Object', (
'assigned_object_type_id', 'region_id', 'site_id', 'device_id', 'virtual_machine_id', 'vlan_id',
)),

View File

@ -2,9 +2,9 @@ import django_filters
from copy import deepcopy
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.db.models import Q
from django_filters.exceptions import FieldLookupError
from django_filters.utils import get_model_field, resolve_field
from django.shortcuts import get_object_or_404
from django.utils.translation import gettext as _
from extras.choices import CustomFieldFilterLogicChoices
@ -89,9 +89,12 @@ class BaseFilterSet(django_filters.FilterSet):
self.base_filters = self.__class__.get_filters()
# Apply any referenced SavedFilters
if data and 'filter' in data:
if data and ('filter' in data or 'filter_id' in data):
data = data.copy() # Get a mutable copy
saved_filters = SavedFilter.objects.filter(pk__in=data.pop('filter'))
saved_filters = SavedFilter.objects.filter(
Q(slug__in=data.pop('filter', [])) |
Q(pk__in=data.pop('filter_id', []))
)
for sf in saved_filters:
for key, value in sf.parameters.items():
# QueryDicts are... fun

View File

@ -141,7 +141,7 @@ class NetBoxModelFilterSetForm(BootstrapMixin, CustomFieldsMixin, SavedFiltersMi
# Limit saved filters to those applicable to the form's model
content_type = ContentType.objects.get_for_model(self.model)
self.fields['filter'].widget.add_query_params({
self.fields['filter_id'].widget.add_query_params({
'content_type_id': content_type.pk,
})

View File

@ -31,7 +31,7 @@ class TenantGroupFilterForm(NetBoxModelFilterSetForm):
class TenantFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
model = Tenant
fieldsets = (
(None, ('q', 'filter', 'tag', 'group_id')),
(None, ('q', 'filter_id', 'tag', 'group_id')),
('Contacts', ('contact', 'contact_role', 'contact_group'))
)
group_id = DynamicModelMultipleChoiceField(

View File

@ -309,7 +309,7 @@ def applied_filters(context, model, form, query_params):
})
save_link = None
if user.has_perm('extras.add_savedfilter') and 'filter' not in context['request'].GET:
if user.has_perm('extras.add_savedfilter') and 'filter_id' not in context['request'].GET:
content_type = ContentType.objects.get_for_model(model).pk
parameters = context['request'].GET.urlencode()
url = reverse('extras:savedfilter_add')

View File

@ -30,7 +30,7 @@ class ClusterGroupFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
model = ClusterGroup
tag = TagFilterField(model)
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Contacts', ('contact', 'contact_role', 'contact_group')),
)
@ -38,7 +38,7 @@ class ClusterGroupFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
class ClusterFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilterSetForm):
model = Cluster
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('group_id', 'type_id', 'status')),
('Location', ('region_id', 'site_group_id', 'site_id')),
('Tenant', ('tenant_group_id', 'tenant_id')),
@ -90,7 +90,7 @@ class VirtualMachineFilterForm(
):
model = VirtualMachine
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Cluster', ('cluster_group_id', 'cluster_type_id', 'cluster_id', 'device_id')),
('Location', ('region_id', 'site_group_id', 'site_id')),
('Attributes', ('status', 'role_id', 'platform_id', 'mac_address', 'has_primary_ip', 'local_context_data')),
@ -175,7 +175,7 @@ class VirtualMachineFilterForm(
class VMInterfaceFilterForm(NetBoxModelFilterSetForm):
model = VMInterface
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Virtual Machine', ('cluster_id', 'virtual_machine_id')),
('Attributes', ('enabled', 'mac_address', 'vrf_id')),
)

View File

@ -28,7 +28,7 @@ class WirelessLANGroupFilterForm(NetBoxModelFilterSetForm):
class WirelessLANFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = WirelessLAN
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('ssid', 'group_id', 'status')),
('Tenant', ('tenant_group_id', 'tenant_id')),
('Authentication', ('auth_type', 'auth_cipher', 'auth_psk')),
@ -67,7 +67,7 @@ class WirelessLANFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
class WirelessLinkFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = WirelessLink
fieldsets = (
(None, ('q', 'filter', 'tag')),
(None, ('q', 'filter_id', 'tag')),
('Attributes', ('ssid', 'status',)),
('Tenant', ('tenant_group_id', 'tenant_id')),
('Authentication', ('auth_type', 'auth_cipher', 'auth_psk')),