Compare commits

...

5 Commits

Author SHA1 Message Date
Daniel Sheppard
ef7880a013 Add test
Some checks failed
CI / build (20.x, 3.10) (push) Has been cancelled
CI / build (20.x, 3.11) (push) Has been cancelled
CI / build (20.x, 3.12) (push) Has been cancelled
2025-08-05 08:55:49 -05:00
Daniel Sheppard
8fd8493d11 Fix image path construction
Some checks failed
CI / build (20.x, 3.10) (push) Has been cancelled
CI / build (20.x, 3.11) (push) Has been cancelled
CI / build (20.x, 3.12) (push) Has been cancelled
2025-07-30 23:14:45 -05:00
Daniel Sheppard
db805053d9 Additional Unblackening
Some checks failed
CI / build (20.x, 3.10) (push) Has been cancelled
CI / build (20.x, 3.11) (push) Has been cancelled
CI / build (20.x, 3.12) (push) Has been cancelled
2025-07-28 10:00:43 -05:00
Daniel Sheppard
cf4db67e0b Unblacken code 2025-07-28 09:55:15 -05:00
Daniel Sheppard
f48e1cb534 Fixes: #19669 - Add an API endpoint to download image attachments 2025-07-24 14:16:02 -05:00
2 changed files with 47 additions and 0 deletions

View File

@@ -1,5 +1,7 @@
from django.conf import settings
from django.http import Http404 from django.http import Http404
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.views.static import serve
from django_rq.queues import get_connection from django_rq.queues import get_connection
from drf_spectacular.utils import extend_schema, extend_schema_view from drf_spectacular.utils import extend_schema, extend_schema_view
from rest_framework import status from rest_framework import status
@@ -200,6 +202,17 @@ class ImageAttachmentViewSet(NetBoxModelViewSet):
serializer_class = serializers.ImageAttachmentSerializer serializer_class = serializers.ImageAttachmentSerializer
filterset_class = filtersets.ImageAttachmentFilterSet filterset_class = filtersets.ImageAttachmentFilterSet
@action(
methods=['GET'],
detail=True,
url_path='download',
url_name='download',
)
def download(self, request, pk, *args, **kwargs):
obj = get_object_or_404(self.queryset, pk=pk)
# Render and return the elevation as an SVG drawing with the correct content type
return serve(request, obj.image.name, document_root=settings.MEDIA_ROOT)
# #
# Journal entries # Journal entries

View File

@@ -1,6 +1,8 @@
import datetime import datetime
from PIL import Image
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.core.files.base import File
from django.urls import reverse from django.urls import reverse
from django.utils.timezone import make_aware, now from django.utils.timezone import make_aware, now
from rest_framework import status from rest_framework import status
@@ -616,6 +618,38 @@ class ImageAttachmentTest(
) )
ImageAttachment.objects.bulk_create(image_attachments) ImageAttachment.objects.bulk_create(image_attachments)
def test_image_download(self):
self.add_permissions('extras.view_imageattachment')
ct = ContentType.objects.get_for_model(Site)
site = Site.objects.get(name='Site 1', slug='site-1')
image = Image.new('RGB', size=(1, 1), color=(255, 0, 0))
image.save('test_image_download.png', format='PNG')
image_file = File(open('test_image_download.png', 'rb'))
content = image_file.read()
attachment = ImageAttachment(
object_type=ct,
object_id=site.pk,
name='Image Attachment 4',
image_height=1,
image_width=1
)
attachment.image.save('test_image_download.png', image_file, save=True)
attachment.save()
image = ImageAttachment.objects.get(name='Image Attachment 4')
url = reverse('extras-api:imageattachment-download', kwargs={'pk': image.pk})
response = self.client.get(url, **self.header)
downloaded_content = b''.join(response.streaming_content)
self.assertEqual(response.headers.get('Content-Type'), 'image/png')
self.assertEqual(response.headers.get('Content-Length'), '69')
self.assertEqual(
response.headers.get('Content-Disposition'), f'inline; filename="site_{site.pk}_Image_Attachment_4.png"'
)
self.assertEqual(content, downloaded_content)
class JournalEntryTest(APIViewTestCases.APIViewTestCase): class JournalEntryTest(APIViewTestCases.APIViewTestCase):
model = JournalEntry model = JournalEntry