diff --git a/docs/release-notes/version-2.9.md b/docs/release-notes/version-2.9.md index 0b6b80b62..5fa6fb6d2 100644 --- a/docs/release-notes/version-2.9.md +++ b/docs/release-notes/version-2.9.md @@ -4,6 +4,7 @@ ### Enhancements +* [#5072](https://github.com/netbox-community/netbox/issues/5072) - Add REST API filters for image attachments * [#5080](https://github.com/netbox-community/netbox/issues/5080) - Add 8P6C, 8P4C, 8P2C port types ### Bug Fixes diff --git a/netbox/extras/api/views.py b/netbox/extras/api/views.py index 289a51c83..a63dbe44d 100644 --- a/netbox/extras/api/views.py +++ b/netbox/extras/api/views.py @@ -140,6 +140,7 @@ class ImageAttachmentViewSet(ModelViewSet): metadata_class = ContentTypeMetadata queryset = ImageAttachment.objects.all() serializer_class = serializers.ImageAttachmentSerializer + filterset_class = filters.ImageAttachmentFilterSet # diff --git a/netbox/extras/filters.py b/netbox/extras/filters.py index e8962da01..1af98e885 100644 --- a/netbox/extras/filters.py +++ b/netbox/extras/filters.py @@ -7,7 +7,7 @@ from tenancy.models import Tenant, TenantGroup from utilities.filters import BaseFilterSet from virtualization.models import Cluster, ClusterGroup from .choices import * -from .models import ConfigContext, CustomField, Graph, ExportTemplate, ObjectChange, JobResult, Tag +from .models import ConfigContext, CustomField, ExportTemplate, Graph, ImageAttachment, JobResult, ObjectChange, Tag __all__ = ( @@ -17,6 +17,7 @@ __all__ = ( 'CustomFieldFilterSet', 'ExportTemplateFilterSet', 'GraphFilterSet', + 'ImageAttachmentFilterSet', 'LocalConfigContextFilterSet', 'ObjectChangeFilterSet', 'TagFilterSet', @@ -104,6 +105,13 @@ class ExportTemplateFilterSet(BaseFilterSet): fields = ['id', 'content_type', 'name', 'template_language'] +class ImageAttachmentFilterSet(BaseFilterSet): + + class Meta: + model = ImageAttachment + fields = ['id', 'content_type', 'object_id', 'name'] + + class TagFilterSet(BaseFilterSet): q = django_filters.CharFilter( method='search', diff --git a/netbox/extras/tests/test_filters.py b/netbox/extras/tests/test_filters.py index 72db138e2..d6e077db4 100644 --- a/netbox/extras/tests/test_filters.py +++ b/netbox/extras/tests/test_filters.py @@ -1,11 +1,11 @@ from django.contrib.contenttypes.models import ContentType from django.test import TestCase -from dcim.models import DeviceRole, Platform, Region, Site +from dcim.models import DeviceRole, Platform, Rack, Region, Site from extras.choices import * from extras.filters import * from extras.utils import FeatureQuery -from extras.models import ConfigContext, ExportTemplate, Graph, Tag +from extras.models import ConfigContext, ExportTemplate, Graph, ImageAttachment, Tag from tenancy.models import Tenant, TenantGroup from virtualization.models import Cluster, ClusterGroup, ClusterType @@ -78,6 +78,84 @@ class ExportTemplateTestCase(TestCase): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) +class ImageAttachmentTestCase(TestCase): + queryset = ImageAttachment.objects.all() + filterset = ImageAttachmentFilterSet + + @classmethod + def setUpTestData(cls): + + site_ct = ContentType.objects.get(app_label='dcim', model='site') + rack_ct = ContentType.objects.get(app_label='dcim', model='rack') + + sites = ( + Site(name='Site 1', slug='site-1'), + Site(name='Site 2', slug='site-2'), + ) + Site.objects.bulk_create(sites) + + racks = ( + Rack(name='Rack 1', site=sites[0]), + Rack(name='Rack 2', site=sites[1]), + ) + Rack.objects.bulk_create(racks) + + image_attachments = ( + ImageAttachment( + content_type=site_ct, + object_id=sites[0].pk, + name='Image Attachment 1', + image='http://example.com/image1.png', + image_height=100, + image_width=100 + ), + ImageAttachment( + content_type=site_ct, + object_id=sites[1].pk, + name='Image Attachment 2', + image='http://example.com/image2.png', + image_height=100, + image_width=100 + ), + ImageAttachment( + content_type=rack_ct, + object_id=racks[0].pk, + name='Image Attachment 3', + image='http://example.com/image3.png', + image_height=100, + image_width=100 + ), + ImageAttachment( + content_type=rack_ct, + object_id=racks[1].pk, + name='Image Attachment 4', + image='http://example.com/image4.png', + image_height=100, + image_width=100 + ) + ) + ImageAttachment.objects.bulk_create(image_attachments) + + def test_id(self): + params = {'id': self.queryset.values_list('pk', flat=True)[:2]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['Image Attachment 1', 'Image Attachment 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_content_type(self): + params = {'content_type': ContentType.objects.get(app_label='dcim', model='site').pk} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_content_type_and_object_id(self): + params = { + 'content_type': ContentType.objects.get(app_label='dcim', model='site').pk, + 'object_id': [Site.objects.first().pk], + } + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + class ConfigContextTestCase(TestCase): queryset = ConfigContext.objects.all() filterset = ConfigContextFilterSet