fix: validate bulk JPEG uploads only once

This commit is contained in:
2026-08-03 15:46:28 +02:00
parent d54fc646ee
commit e1153cfce4
6 changed files with 38 additions and 16 deletions
+2 -2
View File
@@ -34,7 +34,7 @@ Release-Tag oder ein bestimmter Commit verwendet werden:
```bash
/opt/netbox/venv/bin/pip install --upgrade --force-reinstall \
"git+https://git.mrblake.cc/MrBlake/Netbox-Utilities.git@v0.6.0"
"git+https://git.mrblake.cc/MrBlake/Netbox-Utilities.git@v0.6.1"
```
Alternativ kann hinter dem `@` die vollständige Commit-ID stehen.
@@ -179,7 +179,7 @@ Einzel-Upload durch **Mehrere Bilder hochladen** ersetzt. Im Dateidialog können
bis zu 50 Bilder gemeinsam ausgewählt werden. Vor dem Speichern zeigt das
Plugin Vorschaubilder und die jeweiligen Dateinamen an.
Alle Dateien werden zunächst mit NetBox' eigener Bildvalidierung geprüft. Ist
Jede Datei wird genau einmal mit NetBox' eigener Bildvalidierung geprüft. Ist
eine Datei ungültig, wird kein Bild aus dieser Auswahl gespeichert. Eine
optionale gemeinsame Beschreibung kann auf alle Bilder angewendet werden; als
Anzeigename bleibt der jeweilige ursprüngliche Dateiname erhalten. Benötigt
+1 -1
View File
@@ -1,6 +1,6 @@
from netbox.plugins import PluginConfig, get_plugin_config
__version__ = "0.6.0"
__version__ = "0.6.1"
class NetBoxUtilitiesConfig(PluginConfig):
+2 -2
View File
@@ -11,7 +11,7 @@ class MultipleImageInput(forms.ClearableFileInput):
allow_multiple_selected = True
class MultipleImageField(forms.ImageField):
class MultipleFileField(forms.FileField):
widget = MultipleImageInput
def clean(self, data, initial=None):
@@ -22,7 +22,7 @@ class MultipleImageField(forms.ImageField):
class BulkImageUploadForm(forms.Form):
images = MultipleImageField(
images = MultipleFileField(
label="Bilder",
widget=MultipleImageInput(
attrs={
+21 -3
View File
@@ -3,6 +3,7 @@ from io import BytesIO
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import SimpleTestCase
from django.utils.datastructures import MultiValueDict
from extras.forms import ImageAttachmentForm
from PIL import Image
from netbox_utilities.forms import BulkImageUploadForm
@@ -10,10 +11,11 @@ from netbox_utilities.forms import BulkImageUploadForm
class BulkImageUploadFormTest(SimpleTestCase):
@staticmethod
def _image(name):
def _image(name, image_format="PNG"):
content = BytesIO()
Image.new("RGB", (2, 2), "white").save(content, format="PNG")
return SimpleUploadedFile(name, content.getvalue(), content_type="image/png")
Image.new("RGB", (2, 2), "white").save(content, format=image_format)
content_type = "image/jpeg" if image_format == "JPEG" else "image/png"
return SimpleUploadedFile(name, content.getvalue(), content_type=content_type)
def test_accepts_multiple_images(self):
files = MultiValueDict({"images": [self._image("front.png"), self._image("rear.png")]})
@@ -24,6 +26,22 @@ class BulkImageUploadFormTest(SimpleTestCase):
self.assertEqual(len(form.cleaned_data["images"]), 2)
self.assertEqual(form.cleaned_data["description"], "Dokumentation")
def test_jpegs_are_validated_once_by_netbox(self):
files = MultiValueDict(
{
"images": [
self._image("front.JPG", "JPEG"),
self._image("rear.jpg", "JPEG"),
]
}
)
form = BulkImageUploadForm(data={}, files=files)
self.assertTrue(form.is_valid(), form.errors)
for image in form.cleaned_data["images"]:
image.seek(0)
self.assertIsNotNone(ImageAttachmentForm.base_fields["image"].clean(image))
def test_requires_at_least_one_image(self):
form = BulkImageUploadForm(data={}, files={})
+11 -7
View File
@@ -109,14 +109,18 @@ class BulkImageUploadView(ContentTypePermissionRequiredMixin, View):
@staticmethod
def _build_image_forms(parent, cleaned_data):
return [
ImageAttachmentForm(
data={"name": "", "description": cleaned_data["description"]},
files={"image": image},
instance=ImageAttachment(parent=parent),
image_forms = []
for image in cleaned_data["images"]:
if hasattr(image, "seek"):
image.seek(0)
image_forms.append(
ImageAttachmentForm(
data={"name": "", "description": cleaned_data["description"]},
files={"image": image},
instance=ImageAttachment(parent=parent),
)
)
for image in cleaned_data["images"]
]
return image_forms
def _return_url(self, request, parent):
candidate = request.POST.get("return_url") or request.GET.get("return_url")
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "netbox-utilities"
version = "0.6.0"
version = "0.6.1"
description = "Navigation, tenant utilities, bulk image/module upload, and atomic rack reordering for NetBox 4.6"
readme = "README.md"
requires-python = ">=3.12"