Coverage for netbox_data_import/template_content.py: 94.74%
19 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-30 09:47 +0000
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-30 09:47 +0000
1# SPDX-License-Identifier: Apache-2.0
2# Copyright (C) 2025 Marcin Zieba <marcinpsk@gmail.com>
3from netbox.plugins import PluginTemplateExtension
5from . import branching
6from .models import stored_import_source
8IP_FIELD_LABELS = {
9 "primary_ip4": "Primary IPv4",
10 "primary_ip6": "Primary IPv6",
11 "oob_ip": "Out-of-band IP",
12}
15class DeviceImportDataExtension(PluginTemplateExtension):
16 """Adds an import data card to the Device detail page.
18 NetBox appends plugin content to the end of a column, so the closest supported position to
19 the Tags panel is the left column, below the rack elevation drawing that ends the right one.
20 """
22 models = ["dcim.device"]
24 def left_page(self):
25 """Render import data card for the Device detail page left column."""
26 # A branch shows the notice on every Device, so the card reads no plugin data there.
27 if branching.active_branch() is not None:
28 return self.render("netbox_data_import/device_import_data_main_only.html")
29 obj = self.context.get("object")
30 import_source = stored_import_source(obj)
31 if import_source is None:
32 return ""
34 # Show which of the stored IPs NetBox now holds natively.
35 ip_status = {}
36 for field, value in import_source.unassigned_ips.items():
37 native = getattr(obj, field, None)
38 ip_status[field] = {
39 "label": IP_FIELD_LABELS.get(field, field),
40 "value": value,
41 "in_netbox": bool(native),
42 "native_value": str(native.address) if native is not None and hasattr(native, "address") else "",
43 }
45 return self.render(
46 "netbox_data_import/device_import_data.html",
47 extra_context={
48 "import_source": import_source,
49 "extra_columns": import_source.extra_columns,
50 "ip_status": ip_status,
51 "device": obj,
52 },
53 )
56template_extensions = [DeviceImportDataExtension]