From 1b9970b5dd8e4767218b2aa4b53349c4237138fc Mon Sep 17 00:00:00 2001 From: Louis Date: Wed, 23 Sep 2026 13:07:45 +0200 Subject: [PATCH] fix: show rack elevation errors in the exported document Rack SVG failures were only logged, leaving racks silently without an image. The error is now written into the document next to the rack so the cause (e.g. missing rack_elevation.css in STATIC_ROOT) is visible. Co-Authored-By: Claude Opus 5.5 --- netbox_customer_export/rack_svg.py | 8 ++++---- netbox_customer_export/sections.py | 10 +++++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/netbox_customer_export/rack_svg.py b/netbox_customer_export/rack_svg.py index 6ced7d8..7701bdf 100644 --- a/netbox_customer_export/rack_svg.py +++ b/netbox_customer_export/rack_svg.py @@ -8,7 +8,7 @@ logger = logging.getLogger("netbox_customer_export") def render_rack_svg(rack, face, user): - """Gibt das SVG als String zurück oder None bei Fehlern. + """Gibt (svg, fehler) zurück – genau einer der beiden Werte ist None. Ist ``rack_svg_renderer`` gesetzt (z.B. der Offline-Renderer aus Netbox-Utilities, der mehrere Geräte pro HE korrekt darstellt), wird dieser aufgerufen: ``fn(rack=..., face=..., user=...)``. @@ -22,7 +22,7 @@ def render_rack_svg(rack, face, user): from dcim.svg import RackElevationSVG svg = RackElevationSVG(rack, user=user, include_images=False, base_url="").render(face) - return svg.tostring() if hasattr(svg, "tostring") else str(svg) - except Exception: # noqa: BLE001 – ein defektes Rack soll nicht den ganzen Export abbrechen + return (svg.tostring() if hasattr(svg, "tostring") else str(svg)), None + except Exception as e: # noqa: BLE001 – ein defektes Rack soll nicht den ganzen Export abbrechen logger.exception("Rack-SVG für %s (%s) fehlgeschlagen", rack, face) - return None + return None, f"{type(e).__name__}: {e}" diff --git a/netbox_customer_export/sections.py b/netbox_customer_export/sections.py index b940afe..1425a42 100644 --- a/netbox_customer_export/sections.py +++ b/netbox_customer_export/sections.py @@ -172,13 +172,17 @@ def racks(scope, opts): ) ) if opts.get("rack_svg"): - images = [] + images, errors = [], [] for face in opts.get("rack_faces") or ["front"]: - svg = render_rack_svg(rack, face, scope.user) + caption = "Vorderseite" if face == "front" else "Rückseite" + svg, error = render_rack_svg(rack, face, scope.user) if svg: - images.append((svg, "Vorderseite" if face == "front" else "Rückseite")) + images.append((svg, caption)) + else: + errors.append(f"Rack-Ansicht ({caption}) konnte nicht erzeugt werden: {error}") if images: blocks.append(IMAGES(images)) + blocks += [P(e) for e in errors] if opts.get("rack_devices"): devs = scope.restrict(rack.devices.all()).select_related("device_type__manufacturer").order_by("-position", "name") if devs.exists():