diff --git a/netbox/netbox/search/__init__.py b/netbox/netbox/search/__init__.py index 590188f21e5..76898be133b 100644 --- a/netbox/netbox/search/__init__.py +++ b/netbox/netbox/search/__init__.py @@ -1,6 +1,9 @@ from collections import namedtuple +from decimal import Decimal +from django.core.exceptions import FieldDoesNotExist from django.db import models +from netaddr import IPAddress, IPNetwork from ipam.fields import IPAddressField, IPNetworkField from netbox.registry import registry @@ -56,6 +59,24 @@ def get_field_type(instance, field_name): return FieldTypes.INTEGER return FieldTypes.STRING + @staticmethod + def get_attr_type(instance, field_name): + """ + Return the data type of the specified object attribute. + """ + value = getattr(instance, field_name) + if type(value) is str: + return FieldTypes.STRING + if type(value) is int: + return FieldTypes.INTEGER + if type(value) in (float, Decimal): + return FieldTypes.FLOAT + if type(value) is IPNetwork: + return FieldTypes.CIDR + if type(value) is IPAddress: + return FieldTypes.INET + return FieldTypes.STRING + @staticmethod def get_field_value(instance, field_name): """ @@ -82,7 +103,11 @@ def to_cache(cls, instance, custom_fields=None): # Capture built-in fields for name, weight in cls.fields: - type_ = cls.get_field_type(instance, name) + try: + type_ = cls.get_field_type(instance, name) + except FieldDoesNotExist: + # Not a concrete field; handle as an object attribute + type_ = cls.get_attr_type(instance, name) value = cls.get_field_value(instance, name) if type_ and value: values.append( diff --git a/netbox/netbox/tables/tables.py b/netbox/netbox/tables/tables.py index afef74752cc..31502f6c507 100644 --- a/netbox/netbox/tables/tables.py +++ b/netbox/netbox/tables/tables.py @@ -263,9 +263,11 @@ def __init__(self, data, highlight=None, **kwargs): super().__init__(data, **kwargs) def render_field(self, value, record): - if hasattr(record.object, value): - return title(record.object._meta.get_field(value).verbose_name) - return value + try: + model_field = record.object._meta.get_field(value) + return title(model_field.verbose_name) + except FieldDoesNotExist: + return value def render_value(self, value): if not self.highlight: