fix: render partial-width devices in rack SVG

This commit is contained in:
2026-08-12 15:41:40 +02:00
parent 7dc9b4d91d
commit c663069825
5 changed files with 40 additions and 11 deletions
+1 -1
View File
@@ -36,7 +36,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.8.5"
"git+https://git.mrblake.cc/MrBlake/Netbox-Utilities.git@v0.8.6"
```
Alternativ kann hinter dem `@` die vollständige Commit-ID stehen.
+1 -1
View File
@@ -1,6 +1,6 @@
from netbox.plugins import PluginConfig, get_plugin_config
__version__ = "0.8.5"
__version__ = "0.8.6"
class NetBoxUtilitiesConfig(PluginConfig):
+25 -8
View File
@@ -6,6 +6,7 @@ from functools import wraps
from django import forms
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.db.models import Count, Q
from django.db.models.signals import post_save, pre_save
from .models import DeviceRackPlacement
@@ -452,14 +453,8 @@ def _install_rack_svg():
@wraps(original_draw_face)
def width_aware_draw_face(elevation, face, opposite=False):
original_draw_face(elevation, face, opposite)
placements = DeviceRackPlacement.objects.filter(
device__rack=elevation.rack,
device__position__isnull=False,
).select_related("device", "device__device_type", "device__role")
for placement in placements:
device = placement.device
if not (device.face == face or device.device_type.is_full_depth):
continue
for device in _partial_width_elevation_devices(elevation.rack, face):
placement = device.netbox_utilities_rack_placement
height = decimal.Decimal(str(device.device_type.u_height))
coords = elevation._get_device_coords(device.position, height)
width = elevation.unit_width / placement.width
@@ -479,6 +474,28 @@ def _install_rack_svg():
RackElevationSVG._netbox_utilities_rack_width_installed = True
def _partial_width_elevation_devices(rack, face):
"""Return the annotated Device instances expected by NetBox's SVG renderer."""
from dcim.models import Device
return (
Device.objects.filter(
rack=rack,
position__gt=0,
device_type__u_height__gt=0,
netbox_utilities_rack_placement__isnull=False,
)
.filter(Q(face=face) | Q(device_type__is_full_depth=True))
.select_related(
"device_type",
"device_type__manufacturer",
"role",
"netbox_utilities_rack_placement",
)
.annotate(devicebay_count=Count("devicebays"))
)
def _validate_before_save(sender, instance, raw=False, **kwargs):
if not raw:
using = kwargs.get("using")
+12
View File
@@ -12,6 +12,7 @@ from django.urls import resolve, reverse
from netbox_utilities.rack_width import (
_cleanup_unracked_placement,
_partial_width_elevation_devices,
available_units_for_device,
horizontal_interval,
include_rack_width_in_fieldsets,
@@ -24,6 +25,17 @@ from netbox_utilities.rack_width import (
class RackWidthTest(SimpleTestCase):
def test_partial_width_svg_devices_include_core_device_bay_annotation(self):
from dcim.choices import DeviceFaceChoices
from dcim.models import Rack
devices = _partial_width_elevation_devices(Rack(pk=3), DeviceFaceChoices.FACE_FRONT)
self.assertIn("devicebay_count", devices.query.annotations)
self.assertIn("netbox_utilities_rack_placement", devices.query.select_related)
self.assertIn("device_type", devices.query.select_related)
self.assertIn("manufacturer", devices.query.select_related["device_type"])
def test_adds_rack_width_fields_to_existing_location_fieldset(self):
from utilities.forms.rendering import FieldSet
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "netbox-utilities"
version = "0.8.5"
version = "0.8.6"
description = "Navigation, tenant utilities, partial-width rack devices, bulk uploads, and rack reordering for NetBox 4.6"
readme = "README.md"
requires-python = ">=3.12"