diff --git a/netbox/circuits/models/circuits.py b/netbox/circuits/models/circuits.py index b2d9d85a0..02ba5209d 100644 --- a/netbox/circuits/models/circuits.py +++ b/netbox/circuits/models/circuits.py @@ -132,6 +132,9 @@ class Circuit(NetBoxModel): def get_absolute_url(self): return reverse('circuits:circuit', args=[self.pk]) + def get_status_color(self): + return CircuitStatusChoices.colors.get(self.status) + class CircuitTermination(WebhooksMixin, ChangeLoggedModel, LinkTermination): circuit = models.ForeignKey( diff --git a/netbox/dcim/models/cables.py b/netbox/dcim/models/cables.py index 0d5c50622..dcc564717 100644 --- a/netbox/dcim/models/cables.py +++ b/netbox/dcim/models/cables.py @@ -286,6 +286,9 @@ class Cable(NetBoxModel): # Update the private pk used in __str__ in case this is a new object (i.e. just got its pk) self._pk = self.pk + def get_status_color(self): + return LinkStatusChoices.colors.get(self.status) + def get_compatible_types(self): """ Return all termination types compatible with termination A. diff --git a/netbox/dcim/models/devices.py b/netbox/dcim/models/devices.py index 9e2c30103..4ee0dec0e 100644 --- a/netbox/dcim/models/devices.py +++ b/netbox/dcim/models/devices.py @@ -1001,6 +1001,9 @@ class Device(NetBoxModel, ConfigContextModel): """ return Device.objects.filter(parent_bay__device=self.pk) + def get_status_color(self): + return DeviceStatusChoices.colors.get(self.status) + class Module(NetBoxModel, ConfigContextModel): """ diff --git a/netbox/dcim/models/power.py b/netbox/dcim/models/power.py index 2a7cba1fe..08f89e3b0 100644 --- a/netbox/dcim/models/power.py +++ b/netbox/dcim/models/power.py @@ -169,3 +169,9 @@ class PowerFeed(NetBoxModel, PathEndpoint, LinkTermination): @property def parent_object(self): return self.power_panel + + def get_type_color(self): + return PowerFeedTypeChoices.colors.get(self.type) + + def get_status_color(self): + return PowerFeedStatusChoices.colors.get(self.status) diff --git a/netbox/dcim/models/racks.py b/netbox/dcim/models/racks.py index 15aeee4ca..8f6bde3fb 100644 --- a/netbox/dcim/models/racks.py +++ b/netbox/dcim/models/racks.py @@ -247,6 +247,9 @@ class Rack(NetBoxModel): else: return reversed(range(1, self.u_height + 1)) + def get_status_color(self): + return RackStatusChoices.colors.get(self.status) + def get_rack_units(self, user=None, face=DeviceFaceChoices.FACE_FRONT, exclude=None, expand_devices=True): """ Return a list of rack units as dictionaries. Example: {'device': None, 'face': 0, 'id': 48, 'name': 'U48'} diff --git a/netbox/dcim/models/sites.py b/netbox/dcim/models/sites.py index b06fad4f0..53e3bcceb 100644 --- a/netbox/dcim/models/sites.py +++ b/netbox/dcim/models/sites.py @@ -309,6 +309,9 @@ class Site(NetBoxModel): def get_absolute_url(self): return reverse('dcim:site', args=[self.pk]) + def get_status_color(self): + return SiteStatusChoices.colors.get(self.status) + # # Locations diff --git a/netbox/dcim/tables/template_code.py b/netbox/dcim/tables/template_code.py index d8b2089e2..c575cf884 100644 --- a/netbox/dcim/tables/template_code.py +++ b/netbox/dcim/tables/template_code.py @@ -31,7 +31,7 @@ DEVICE_LINK = """ DEVICEBAY_STATUS = """ {% if record.installed_device_id %} - + {{ record.installed_device.get_status_display }} {% else %} @@ -43,7 +43,7 @@ INTERFACE_IPADDRESSES = """
{% for ip in record.ip_addresses.all %} {% if ip.status != 'active' %} - {{ ip }} + {{ ip }} {% else %} {{ ip }} {% endif %} diff --git a/netbox/extras/models/change_logging.py b/netbox/extras/models/change_logging.py index c7ad44985..2c91d97a4 100644 --- a/netbox/extras/models/change_logging.py +++ b/netbox/extras/models/change_logging.py @@ -102,3 +102,6 @@ class ObjectChange(models.Model): def get_absolute_url(self): return reverse('extras:objectchange', args=[self.pk]) + + def get_action_color(self): + return ObjectChangeActionChoices.colors.get(self.action) diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py index 77ba66377..5eb5a4a02 100644 --- a/netbox/extras/models/models.py +++ b/netbox/extras/models/models.py @@ -458,6 +458,9 @@ class JournalEntry(WebhooksMixin, ChangeLoggedModel): def get_absolute_url(self): return reverse('extras:journalentry', args=[self.pk]) + def get_kind_color(self): + return JournalEntryKindChoices.colors.get(self.kind) + class JobResult(models.Model): """ diff --git a/netbox/ipam/models/ip.py b/netbox/ipam/models/ip.py index a6e6967f1..6c9784cde 100644 --- a/netbox/ipam/models/ip.py +++ b/netbox/ipam/models/ip.py @@ -437,6 +437,9 @@ class Prefix(GetAvailablePrefixesMixin, NetBoxModel): self.prefix.prefixlen = value prefix_length = property(fset=_set_prefix_length) + def get_status_color(self): + return PrefixStatusChoices.colors.get(self.status) + def get_parents(self, include_self=False): """ Return all containing Prefixes in the hierarchy. @@ -703,6 +706,9 @@ class IPRange(NetBoxModel): self.end_address.prefixlen = value prefix_length = property(fset=_set_prefix_length) + def get_status_color(self): + return IPRangeStatusChoices.colors.get(self.status) + def get_child_ips(self): """ Return all IPAddresses within this IPRange and VRF. @@ -916,3 +922,9 @@ class IPAddress(NetBoxModel): if self.address is not None: self.address.prefixlen = value mask_length = property(fset=_set_mask_length) + + def get_status_color(self): + return IPAddressStatusChoices.colors.get(self.status) + + def get_role_color(self): + return IPAddressRoleChoices.colors.get(self.role) diff --git a/netbox/ipam/models/vlans.py b/netbox/ipam/models/vlans.py index 4673c8f45..7643a2617 100644 --- a/netbox/ipam/models/vlans.py +++ b/netbox/ipam/models/vlans.py @@ -211,6 +211,9 @@ class VLAN(NetBoxModel): f"{self.group}" }) + def get_status_color(self): + return VLANStatusChoices.colors.get(self.status) + def get_interfaces(self): # Return all device interfaces assigned to this VLAN return Interface.objects.filter( diff --git a/netbox/netbox/tables/columns.py b/netbox/netbox/tables/columns.py index fa8c3d7cf..4be88c995 100644 --- a/netbox/netbox/tables/columns.py +++ b/netbox/netbox/tables/columns.py @@ -167,19 +167,20 @@ class ActionsColumn(tables.Column): class ChoiceFieldColumn(tables.Column): """ - Render a model's static ChoiceField with its value from `get_FOO_display()` as a colored badge. Colors are derived - from the ChoiceSet associated with the model field. + Render a model's static ChoiceField with its value from `get_FOO_display()` as a colored badge. Background color is + set by the instance's get_FOO_color() method, if defined. """ + DEFAULT_BG_COLOR = 'secondary' + def render(self, record, bound_column, value): if value in self.empty_values: return self.default - accessor = tables.A(bound_column.accessor) - field = accessor.get_field(record) - raw_value = accessor.resolve(record) # `value` is from get_FOO_display() - - # Determine the background color to use - bg_color = field.choices.colors.get(raw_value, 'secondary') + # Determine the background color to use (try calling object.get_FOO_color()) + try: + bg_color = getattr(record, f'get_{bound_column.name}_color')() + except AttributeError: + bg_color = self.DEFAULT_BG_COLOR return mark_safe(f'{value}') diff --git a/netbox/templates/circuits/circuit.html b/netbox/templates/circuits/circuit.html index 22713b592..94cad56b3 100644 --- a/netbox/templates/circuits/circuit.html +++ b/netbox/templates/circuits/circuit.html @@ -32,9 +32,7 @@ Status - - {{ object.get_status_display }} - + {% badge object.get_status_display bg_color=object.get_status_color %} Tenant diff --git a/netbox/templates/dcim/cable.html b/netbox/templates/dcim/cable.html index 00704e6ca..d68353274 100644 --- a/netbox/templates/dcim/cable.html +++ b/netbox/templates/dcim/cable.html @@ -19,9 +19,7 @@ Status - - {{ object.get_status_display }} - + {% badge object.get_status_display bg_color=object.get_status_color %} Tenant diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index 3beaed4b4..db3a7868e 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -163,9 +163,7 @@ - + diff --git a/netbox/templates/dcim/powerfeed.html b/netbox/templates/dcim/powerfeed.html index 1824cac19..5157a5ec0 100644 --- a/netbox/templates/dcim/powerfeed.html +++ b/netbox/templates/dcim/powerfeed.html @@ -40,15 +40,11 @@ - + - + diff --git a/netbox/templates/dcim/rack.html b/netbox/templates/dcim/rack.html index 93bd21fd9..6e0da812d 100644 --- a/netbox/templates/dcim/rack.html +++ b/netbox/templates/dcim/rack.html @@ -76,9 +76,7 @@ - + @@ -188,10 +186,10 @@ {{ powerfeed.name }} {% with power_port=powerfeed.connected_endpoint %} {% if power_port %} diff --git a/netbox/templates/dcim/site.html b/netbox/templates/dcim/site.html index 539974b86..5ab3510c7 100644 --- a/netbox/templates/dcim/site.html +++ b/netbox/templates/dcim/site.html @@ -53,9 +53,7 @@ - + diff --git a/netbox/templates/dcim/trace/cable.html b/netbox/templates/dcim/trace/cable.html index 5f8fb01eb..0289e1091 100644 --- a/netbox/templates/dcim/trace/cable.html +++ b/netbox/templates/dcim/trace/cable.html @@ -12,7 +12,7 @@ {% if cable.length %} ({{ cable.length|floatformat }} {{ cable.get_length_unit_display }})
{% endif %} - {{ cable.get_status_display }}
+ {% badge object.get_status_display bg_color=object.get_status_color %}
{% for tag in cable.tags.all %} {% tag tag 'dcim:cable_list' %} {% endfor %} diff --git a/netbox/templates/extras/journalentry.html b/netbox/templates/extras/journalentry.html index 2e7fcbbf5..4a38fb4e3 100644 --- a/netbox/templates/extras/journalentry.html +++ b/netbox/templates/extras/journalentry.html @@ -36,9 +36,7 @@ - +
Status - {{ object.get_status_display }} - {% badge object.get_status_display bg_color=object.get_status_color %}
Role
Type - {{ object.get_type_display }} - {% badge object.get_type_display bg_color=object.get_type_color %}
Status - {{ object.get_status_display }} - {% badge object.get_status_display bg_color=object.get_status_color %}
Connected Device
Status - {{ object.get_status_display }} - {% badge object.get_status_display bg_color=object.get_status_color %}
Role - {{ powerfeed.get_status_display }} + {% badge powerfeed.get_status_display bg_color=powerfeed.get_status_color %} - {{ powerfeed.get_type_display }} + {% badge powerfeed.get_type_display bg_color=powerfeed.get_type_color %}
Status - {{ object.get_status_display }} - {% badge object.get_status_display bg_color=object.get_status_color %}
Tenant
Kind - {{ object.get_kind_display }} - {% badge object.get_kind_display bg_color=object.get_kind_color %}
diff --git a/netbox/templates/generic/object_list.html b/netbox/templates/generic/object_list.html index 59abac016..6141b29f7 100644 --- a/netbox/templates/generic/object_list.html +++ b/netbox/templates/generic/object_list.html @@ -52,7 +52,7 @@ Context: {% endif %} diff --git a/netbox/templates/ipam/ipaddress.html b/netbox/templates/ipam/ipaddress.html index cb1281e53..779d211f5 100644 --- a/netbox/templates/ipam/ipaddress.html +++ b/netbox/templates/ipam/ipaddress.html @@ -48,9 +48,7 @@ Status - - {{ object.get_status_display }} - + {% badge object.get_status_display bg_color=object.get_status_color %} Role diff --git a/netbox/templates/ipam/iprange.html b/netbox/templates/ipam/iprange.html index b549ec7c5..e4f27d68c 100644 --- a/netbox/templates/ipam/iprange.html +++ b/netbox/templates/ipam/iprange.html @@ -55,9 +55,7 @@ Status - - {{ object.get_status_display }} - + {% badge object.get_status_display bg_color=object.get_status_color %} Tenant diff --git a/netbox/templates/ipam/prefix.html b/netbox/templates/ipam/prefix.html index 045f4b9e0..ba3e84911 100644 --- a/netbox/templates/ipam/prefix.html +++ b/netbox/templates/ipam/prefix.html @@ -75,9 +75,7 @@ Status - - {{ object.get_status_display }} - + {% badge object.get_status_display bg_color=object.get_status_color %} Role diff --git a/netbox/templates/ipam/vlan.html b/netbox/templates/ipam/vlan.html index 367ae3641..dc19bd34e 100644 --- a/netbox/templates/ipam/vlan.html +++ b/netbox/templates/ipam/vlan.html @@ -58,9 +58,7 @@ Status - - {{ object.get_status_display }} - + {% badge object.get_status_display bg_color=object.get_status_color %} Role diff --git a/netbox/templates/virtualization/virtualmachine.html b/netbox/templates/virtualization/virtualmachine.html index 140d1ab86..22dd27b97 100644 --- a/netbox/templates/virtualization/virtualmachine.html +++ b/netbox/templates/virtualization/virtualmachine.html @@ -19,9 +19,7 @@ Status - - {{ object.get_status_display }} - + {% badge object.get_status_display bg_color=object.get_status_color %} Role diff --git a/netbox/templates/wireless/wirelesslink.html b/netbox/templates/wireless/wirelesslink.html index 6ad88729d..4795dcdde 100644 --- a/netbox/templates/wireless/wirelesslink.html +++ b/netbox/templates/wireless/wirelesslink.html @@ -17,9 +17,7 @@ - + diff --git a/netbox/utilities/templates/builtins/badge.html b/netbox/utilities/templates/builtins/badge.html index 4057eddc1..d12c6108e 100644 --- a/netbox/utilities/templates/builtins/badge.html +++ b/netbox/utilities/templates/builtins/badge.html @@ -1 +1 @@ -{% if value or show_empty %}{{ value }}{% endif %} +{% if value or show_empty %}{{ value }}{% endif %} diff --git a/netbox/utilities/templatetags/builtins/tags.py b/netbox/utilities/templatetags/builtins/tags.py index a72a87d56..a6c631efc 100644 --- a/netbox/utilities/templatetags/builtins/tags.py +++ b/netbox/utilities/templatetags/builtins/tags.py @@ -19,18 +19,18 @@ def tag(value, viewname=None): @register.inclusion_tag('builtins/badge.html') -def badge(value, bg_class='secondary', show_empty=False): +def badge(value, bg_color='secondary', show_empty=False): """ Display the specified number as a badge. Args: value: The value to be displayed within the badge - bg_class: Bootstrap 5 background CSS name + bg_color: Background color CSS name show_empty: If true, display the badge even if value is None or zero """ return { 'value': value, - 'bg_class': bg_class, + 'bg_color': bg_color, 'show_empty': show_empty, } diff --git a/netbox/virtualization/models.py b/netbox/virtualization/models.py index 5e41064c4..586bb8a9e 100644 --- a/netbox/virtualization/models.py +++ b/netbox/virtualization/models.py @@ -322,6 +322,9 @@ class VirtualMachine(NetBoxModel, ConfigContextModel): field: f"The specified IP address ({ip}) is not assigned to this VM.", }) + def get_status_color(self): + return VirtualMachineStatusChoices.colors.get(self.status) + @property def primary_ip(self): if get_config().PREFER_IPV4 and self.primary_ip4: diff --git a/netbox/wireless/models.py b/netbox/wireless/models.py index 055ea1672..0543e5621 100644 --- a/netbox/wireless/models.py +++ b/netbox/wireless/models.py @@ -177,6 +177,9 @@ class WirelessLink(WirelessAuthenticationBase, NetBoxModel): def get_absolute_url(self): return reverse('wireless:wirelesslink', args=[self.pk]) + def get_status_color(self): + return LinkStatusChoices.colors.get(self.status) + def clean(self): # Validate interface types
Status - {{ object.get_status_display }} - {% badge object.get_status_display bg_color=object.get_status_color %}
SSID