diff --git a/docs/release-notes/version-2.7.md b/docs/release-notes/version-2.7.md index afce2ef70..251b063ae 100644 --- a/docs/release-notes/version-2.7.md +++ b/docs/release-notes/version-2.7.md @@ -5,6 +5,7 @@ ### Enhancements * [#3676](https://github.com/netbox-community/netbox/issues/3676) - Reference VRF by name rather than RD during IP/prefix import +* [#4147](https://github.com/netbox-community/netbox/issues/4147) - Use absolute URLs in rack elevation SVG renderings ### Bug Fixes diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index 34ba0c47d..1041a0f41 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -225,7 +225,8 @@ class RackViewSet(CustomFieldModelViewSet): unit_width=data['unit_width'], unit_height=data['unit_height'], legend_width=data['legend_width'], - include_images=data['include_images'] + include_images=data['include_images'], + base_url=request.build_absolute_uri('/') ) return HttpResponse(drawing.tostring(), content_type='image/svg+xml') diff --git a/netbox/dcim/elevations.py b/netbox/dcim/elevations.py index a1af3968c..ea780b2d9 100644 --- a/netbox/dcim/elevations.py +++ b/netbox/dcim/elevations.py @@ -15,10 +15,15 @@ class RackElevationSVG: :param rack: A NetBox Rack instance :param include_images: If true, the SVG document will embed front/rear device face images, where available + :param base_url: Base URL for links within the SVG document. If none, links will be relative. """ - def __init__(self, rack, include_images=True): + def __init__(self, rack, include_images=True, base_url=None): self.rack = rack self.include_images = include_images + if base_url is not None: + self.base_url = base_url.rstrip('/') + else: + self.base_url = '' def _get_device_description(self, device): return '{} ({}) — {} ({}U) {} {}'.format( @@ -69,7 +74,7 @@ class RackElevationSVG: color = device.device_role.color link = drawing.add( drawing.a( - href=reverse('dcim:device', kwargs={'pk': device.pk}), + href='{}{}'.format(self.base_url, reverse('dcim:device', kwargs={'pk': device.pk})), target='_top', fill='black' ) @@ -81,7 +86,7 @@ class RackElevationSVG: # Embed front device type image if one exists if self.include_images and device.device_type.front_image: - url = device.device_type.front_image.url + url = '{}{}'.format(self.base_url, device.device_type.front_image.url) image = drawing.image(href=url, insert=start, size=end, class_='device-image') image.fit(scale='slice') link.add(image) diff --git a/netbox/dcim/models/__init__.py b/netbox/dcim/models/__init__.py index 63a320c78..f8a15ced9 100644 --- a/netbox/dcim/models/__init__.py +++ b/netbox/dcim/models/__init__.py @@ -682,7 +682,8 @@ class Rack(ChangeLoggedModel, CustomFieldModel): unit_width=RACK_ELEVATION_UNIT_WIDTH_DEFAULT, unit_height=RACK_ELEVATION_UNIT_HEIGHT_DEFAULT, legend_width=RACK_ELEVATION_LEGEND_WIDTH_DEFAULT, - include_images=True + include_images=True, + base_url=None ): """ Return an SVG of the rack elevation @@ -693,8 +694,9 @@ class Rack(ChangeLoggedModel, CustomFieldModel): height of the elevation :param legend_width: Width of the unit legend, in pixels :param include_images: Embed front/rear device images where available + :param base_url: Base URL for links and images. If none, URLs will be relative. """ - elevation = RackElevationSVG(self, include_images=include_images) + elevation = RackElevationSVG(self, include_images=include_images, base_url=base_url) return elevation.render(face, unit_width, unit_height, legend_width)