diff --git a/netbox/circuits/apps.py b/netbox/circuits/apps.py index bc0b7d87d..3acf3b98c 100644 --- a/netbox/circuits/apps.py +++ b/netbox/circuits/apps.py @@ -6,4 +6,4 @@ class CircuitsConfig(AppConfig): verbose_name = "Circuits" def ready(self): - import circuits.signals + from . import signals, search diff --git a/netbox/circuits/search_indexes.py b/netbox/circuits/search.py similarity index 82% rename from netbox/circuits/search_indexes.py rename to netbox/circuits/search.py index e2ae23348..8c40acaaa 100644 --- a/netbox/circuits/search_indexes.py +++ b/netbox/circuits/search.py @@ -1,13 +1,13 @@ import circuits.filtersets import circuits.tables from circuits.models import Circuit, Provider, ProviderNetwork -from django.db import models from netbox.search.models import SearchMixin +from netbox.search import register_search from utilities.utils import count_related +@register_search(Provider) class ProviderIndex(SearchMixin): - model = Provider queryset = Provider.objects.annotate(count_circuits=count_related(Circuit, 'provider')) filterset = circuits.filtersets.ProviderFilterSet table = circuits.tables.ProviderTable @@ -15,8 +15,8 @@ class ProviderIndex(SearchMixin): choice_header = 'Circuits' +@register_search(Circuit) class CircuitIndex(SearchMixin): - model = Circuit queryset = Circuit.objects.prefetch_related( 'type', 'provider', 'tenant', 'tenant__group', 'terminations__site' ) @@ -26,17 +26,10 @@ class CircuitIndex(SearchMixin): choice_header = 'Circuits' +@register_search(ProviderNetwork) class ProviderNetworkIndex(SearchMixin): - model = ProviderNetwork queryset = ProviderNetwork.objects.prefetch_related('provider') filterset = circuits.filtersets.ProviderNetworkFilterSet table = circuits.tables.ProviderNetworkTable url = 'circuits:providernetwork_list' choice_header = 'Circuits' - - -CIRCUIT_SEARCH_TYPES = { - 'provider': ProviderIndex, - 'circuit': CircuitIndex, - 'providernetwork': ProviderNetworkIndex, -} diff --git a/netbox/dcim/apps.py b/netbox/dcim/apps.py index 4be2df659..bfb09e601 100644 --- a/netbox/dcim/apps.py +++ b/netbox/dcim/apps.py @@ -8,7 +8,7 @@ class DCIMConfig(AppConfig): verbose_name = "DCIM" def ready(self): - import dcim.signals + from . import signals, search from .models import CableTermination # Register denormalized fields diff --git a/netbox/dcim/search_indexes.py b/netbox/dcim/search.py similarity index 86% rename from netbox/dcim/search_indexes.py rename to netbox/dcim/search.py index 28c5d6bcd..2fbe8c322 100644 --- a/netbox/dcim/search_indexes.py +++ b/netbox/dcim/search.py @@ -14,11 +14,12 @@ from dcim.models import ( VirtualChassis, ) from netbox.search.models import SearchMixin +from netbox.search import register_search from utilities.utils import count_related +@register_search(Site) class SiteIndex(SearchMixin): - model = Site queryset = Site.objects.prefetch_related('region', 'tenant', 'tenant__group') filterset = dcim.filtersets.SiteFilterSet table = dcim.tables.SiteTable @@ -26,8 +27,8 @@ class SiteIndex(SearchMixin): choice_header = 'DCIM' +@register_search(Rack) class RackIndex(SearchMixin): - model = Rack queryset = Rack.objects.prefetch_related('site', 'location', 'tenant', 'tenant__group', 'role').annotate( device_count=count_related(Device, 'rack') ) @@ -37,8 +38,8 @@ class RackIndex(SearchMixin): choice_header = 'DCIM' +@register_search(RackReservation) class RackReservationIndex(SearchMixin): - model = RackReservation queryset = RackReservation.objects.prefetch_related('rack', 'user') filterset = dcim.filtersets.RackReservationFilterSet table = dcim.tables.RackReservationTable @@ -46,8 +47,8 @@ class RackReservationIndex(SearchMixin): choice_header = 'DCIM' +@register_search(Location) class LocationIndex(SearchMixin): - model = Site queryset = Location.objects.add_related_count( Location.objects.add_related_count(Location.objects.all(), Device, 'location', 'device_count', cumulative=True), Rack, @@ -61,8 +62,8 @@ class LocationIndex(SearchMixin): choice_header = 'DCIM' +@register_search(DeviceType) class DeviceTypeIndex(SearchMixin): - model = DeviceType queryset = DeviceType.objects.prefetch_related('manufacturer').annotate( instance_count=count_related(Device, 'device_type') ) @@ -72,8 +73,8 @@ class DeviceTypeIndex(SearchMixin): choice_header = 'DCIM' +@register_search(Device) class DeviceIndex(SearchMixin): - model = Device queryset = Device.objects.prefetch_related( 'device_type__manufacturer', 'device_role', @@ -90,8 +91,8 @@ class DeviceIndex(SearchMixin): choice_header = 'DCIM' +@register_search(ModuleType) class ModuleTypeIndex(SearchMixin): - model = ModuleType queryset = ModuleType.objects.prefetch_related('manufacturer').annotate( instance_count=count_related(Module, 'module_type') ) @@ -101,8 +102,8 @@ class ModuleTypeIndex(SearchMixin): choice_header = 'DCIM' +@register_search(Module) class ModuleIndex(SearchMixin): - model = Module queryset = Module.objects.prefetch_related( 'module_type__manufacturer', 'device', @@ -114,8 +115,8 @@ class ModuleIndex(SearchMixin): choice_header = 'DCIM' +@register_search(VirtualChassis) class VirtualChassisIndex(SearchMixin): - model = VirtualChassis queryset = VirtualChassis.objects.prefetch_related('master').annotate( member_count=count_related(Device, 'virtual_chassis') ) @@ -125,8 +126,8 @@ class VirtualChassisIndex(SearchMixin): choice_header = 'DCIM' +@register_search(Cable) class CableIndex(SearchMixin): - model = Cable queryset = Cable.objects.all() filterset = dcim.filtersets.CableFilterSet table = dcim.tables.CableTable @@ -134,25 +135,10 @@ class CableIndex(SearchMixin): choice_header = 'DCIM' +@register_search(PowerFeed) class PowerFeedIndex(SearchMixin): - model = PowerFeed queryset = PowerFeed.objects.all() filterset = dcim.filtersets.PowerFeedFilterSet table = dcim.tables.PowerFeedTable url = 'dcim:powerfeed_list' choice_header = 'DCIM' - - -DCIM_SEARCH_TYPES = { - 'site': SiteIndex, - 'rack': RackIndex, - 'rackreservation': RackReservationIndex, - 'location': LocationIndex, - 'devicetype': DeviceTypeIndex, - 'device': DeviceIndex, - 'moduletype': ModuleTypeIndex, - 'module': ModuleIndex, - 'virtualchassis': VirtualChassisIndex, - 'cable': CableIndex, - 'powerfeed': PowerFeedIndex, -} diff --git a/netbox/extras/apps.py b/netbox/extras/apps.py index 7500157c0..965eb033e 100644 --- a/netbox/extras/apps.py +++ b/netbox/extras/apps.py @@ -5,5 +5,4 @@ class ExtrasConfig(AppConfig): name = "extras" def ready(self): - import extras.lookups - import extras.signals + from . import lookups, search, signals diff --git a/netbox/extras/registry.py b/netbox/extras/registry.py index b748b6f90..f89499842 100644 --- a/netbox/extras/registry.py +++ b/netbox/extras/registry.py @@ -29,4 +29,5 @@ registry['model_features'] = { feature: collections.defaultdict(set) for feature in EXTRAS_FEATURES } registry['denormalized_fields'] = collections.defaultdict(list) +registry['search'] = collections.defaultdict(dict) registry['views'] = collections.defaultdict(dict) diff --git a/netbox/extras/search_indexes.py b/netbox/extras/search.py similarity index 100% rename from netbox/extras/search_indexes.py rename to netbox/extras/search.py diff --git a/netbox/ipam/apps.py b/netbox/ipam/apps.py index 413c8c1bc..4b0820fef 100644 --- a/netbox/ipam/apps.py +++ b/netbox/ipam/apps.py @@ -6,4 +6,4 @@ class IPAMConfig(AppConfig): verbose_name = "IPAM" def ready(self): - import ipam.signals + from . import signals, search diff --git a/netbox/ipam/search_indexes.py b/netbox/ipam/search.py similarity index 82% rename from netbox/ipam/search_indexes.py rename to netbox/ipam/search.py index 232d13f0d..4701fa07c 100644 --- a/netbox/ipam/search_indexes.py +++ b/netbox/ipam/search.py @@ -1,13 +1,12 @@ import ipam.filtersets import ipam.tables -from django.db import models from ipam.models import ASN, VLAN, VRF, Aggregate, IPAddress, Prefix, Service from netbox.search.models import SearchMixin -from utilities.utils import count_related +from netbox.search import register_search +@register_search(VRF) class VRFIndex(SearchMixin): - model = VRF queryset = VRF.objects.prefetch_related('tenant', 'tenant__group') filterset = ipam.filtersets.VRFFilterSet table = ipam.tables.VRFTable @@ -15,8 +14,8 @@ class VRFIndex(SearchMixin): choice_header = 'IPAM' +@register_search(Aggregate) class AggregateIndex(SearchMixin): - model = Aggregate queryset = Aggregate.objects.prefetch_related('rir') filterset = ipam.filtersets.AggregateFilterSet table = ipam.tables.AggregateTable @@ -24,8 +23,8 @@ class AggregateIndex(SearchMixin): choice_header = 'IPAM' +@register_search(Prefix) class PrefixIndex(SearchMixin): - model = Prefix queryset = Prefix.objects.prefetch_related( 'site', 'vrf__tenant', 'tenant', 'tenant__group', 'vlan', 'role' ) @@ -35,8 +34,8 @@ class PrefixIndex(SearchMixin): choice_header = 'IPAM' +@register_search(IPAddress) class IPAddressIndex(SearchMixin): - model = IPAddress queryset = IPAddress.objects.prefetch_related('vrf__tenant', 'tenant', 'tenant__group') filterset = ipam.filtersets.IPAddressFilterSet table = ipam.tables.IPAddressTable @@ -44,8 +43,8 @@ class IPAddressIndex(SearchMixin): choice_header = 'IPAM' +@register_search(VLAN) class VLANIndex(SearchMixin): - model = VLAN queryset = VLAN.objects.prefetch_related('site', 'group', 'tenant', 'tenant__group', 'role') filterset = ipam.filtersets.VLANFilterSet table = ipam.tables.VLANTable @@ -53,8 +52,8 @@ class VLANIndex(SearchMixin): choice_header = 'IPAM' +@register_search(ASN) class ASNIndex(SearchMixin): - model = ASN queryset = ASN.objects.prefetch_related('rir', 'tenant', 'tenant__group') filterset = ipam.filtersets.ASNFilterSet table = ipam.tables.ASNTable @@ -62,21 +61,10 @@ class ASNIndex(SearchMixin): choice_header = 'IPAM' +@register_search(Service) class ServiceIndex(SearchMixin): - model = Service queryset = Service.objects.prefetch_related('device', 'virtual_machine') filterset = ipam.filtersets.ServiceFilterSet table = ipam.tables.ServiceTable url = 'ipam:service_list' choice_header = 'IPAM' - - -IPAM_SEARCH_TYPES = { - 'vrf': VRFIndex, - 'aggregate': AggregateIndex, - 'prefix': PrefixIndex, - 'ipaddress': IPAddressIndex, - 'vlan': VLANIndex, - 'asn': ASNIndex, - 'service': ServiceIndex, -} diff --git a/netbox/netbox/search/__init__.py b/netbox/netbox/search/__init__.py index e69de29bb..67d9d9344 100644 --- a/netbox/netbox/search/__init__.py +++ b/netbox/netbox/search/__init__.py @@ -0,0 +1 @@ +from .register import register_search diff --git a/netbox/netbox/search/backends.py b/netbox/netbox/search/backends.py index eca889019..86cd2538b 100644 --- a/netbox/netbox/search/backends.py +++ b/netbox/netbox/search/backends.py @@ -4,6 +4,8 @@ from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.db.models.signals import post_save, pre_delete from django.urls import reverse + +from extras.registry import registry from netbox.constants import SEARCH_MAX_RESULTS # The cache for the initialized backend. @@ -71,7 +73,12 @@ class SearchBackend(object): pre_delete.connect(self._pre_delete_receiver, model) def get_registry(self): - return self._registered_models + # return self._registered_models + + r = {} + for app_label, models in registry['search'].items(): + r.update(**models) + return r # Signalling hooks. diff --git a/netbox/netbox/search/hierarchy.py b/netbox/netbox/search/hierarchy.py deleted file mode 100644 index 4a1e2e278..000000000 --- a/netbox/netbox/search/hierarchy.py +++ /dev/null @@ -1,30 +0,0 @@ -from circuits.search_indexes import CIRCUIT_SEARCH_TYPES -from dcim.search_indexes import DCIM_SEARCH_TYPES -from extras.search_indexes import JOURNAL_SEARCH_TYPES -from ipam.search_indexes import IPAM_SEARCH_TYPES -from tenancy.search_indexes import TENANCY_SEARCH_TYPES -from virtualization.search_indexes import VIRTUALIZATION_SEARCH_TYPES -from wireless.search_indexes import WIRELESS_SEARCH_TYPES - -SEARCH_TYPE_HIERARCHY = { - 'Circuits': CIRCUIT_SEARCH_TYPES, - 'DCIM': DCIM_SEARCH_TYPES, - 'IPAM': IPAM_SEARCH_TYPES, - 'Tenancy': TENANCY_SEARCH_TYPES, - 'Virtualization': VIRTUALIZATION_SEARCH_TYPES, - 'Wireless': WIRELESS_SEARCH_TYPES, - 'Journal': JOURNAL_SEARCH_TYPES, -} - - -def build_search_types(): - result = dict() - - for app_types in SEARCH_TYPE_HIERARCHY.values(): - for name, items in app_types.items(): - result[name] = items - - return result - - -SEARCH_TYPES = build_search_types() diff --git a/netbox/netbox/search/register.py b/netbox/netbox/search/register.py index f312e5ca9..14c4f239f 100644 --- a/netbox/netbox/search/register.py +++ b/netbox/netbox/search/register.py @@ -6,8 +6,8 @@ from django.apps import apps from django.conf import settings from django.utils.module_loading import module_has_submodule +from extras.registry import registry from .backends import default_search_engine -from .hierarchy import SEARCH_TYPES def get_app_modules(): @@ -19,8 +19,13 @@ def get_app_modules(): def register(): - for name, module in SEARCH_TYPES.items(): - default_search_engine.register(name, module) + + # for name, module in SEARCH_TYPES.items(): + # default_search_engine.register(name, module) + + for app_label, models in registry['search'].items(): + for name, cls in models.items(): + default_search_engine.register(name, cls) for name, module in get_app_modules(): submodule_name = "search_indexes" @@ -37,3 +42,15 @@ def register(): cls_name = cls_obj.model.__name__.lower() if not default_search_engine.is_registered(cls_name, cls_obj): default_search_engine.register(cls_name, cls_obj) + + +def register_search(model): + def _wrapper(cls): + app_label = model._meta.app_label + model_name = model._meta.model_name + + registry['search'][app_label][model_name] = cls + + return cls + + return _wrapper diff --git a/netbox/tenancy/apps.py b/netbox/tenancy/apps.py index 53cb9a056..eeb141152 100644 --- a/netbox/tenancy/apps.py +++ b/netbox/tenancy/apps.py @@ -3,3 +3,6 @@ from django.apps import AppConfig class TenancyConfig(AppConfig): name = 'tenancy' + + def ready(self): + from . import search diff --git a/netbox/tenancy/search_indexes.py b/netbox/tenancy/search.py similarity index 83% rename from netbox/tenancy/search_indexes.py rename to netbox/tenancy/search.py index d3ac76315..502a7606a 100644 --- a/netbox/tenancy/search_indexes.py +++ b/netbox/tenancy/search.py @@ -1,13 +1,13 @@ import tenancy.filtersets import tenancy.tables -from django.db import models from netbox.search.models import SearchMixin +from netbox.search import register_search from tenancy.models import Contact, ContactAssignment, Tenant from utilities.utils import count_related +@register_search(Tenant) class TenantIndex(SearchMixin): - model = Tenant queryset = Tenant.objects.prefetch_related('group') filterset = tenancy.filtersets.TenantFilterSet table = tenancy.tables.TenantTable @@ -15,8 +15,8 @@ class TenantIndex(SearchMixin): choice_header = 'Tenancy' +@register_search(Contact) class ContactIndex(SearchMixin): - model = Contact queryset = Contact.objects.prefetch_related('group', 'assignments').annotate( assignment_count=count_related(ContactAssignment, 'contact') ) @@ -24,9 +24,3 @@ class ContactIndex(SearchMixin): table = tenancy.tables.ContactTable url = 'tenancy:contact_list' choice_header = 'Tenancy' - - -TENANCY_SEARCH_TYPES = { - 'tenant': TenantIndex, - 'contact': ContactIndex, -} diff --git a/netbox/virtualization/apps.py b/netbox/virtualization/apps.py index 35d6e8266..1b6b110df 100644 --- a/netbox/virtualization/apps.py +++ b/netbox/virtualization/apps.py @@ -3,3 +3,6 @@ from django.apps import AppConfig class VirtualizationConfig(AppConfig): name = 'virtualization' + + def ready(self): + from . import search diff --git a/netbox/virtualization/search_indexes.py b/netbox/virtualization/search.py similarity index 79% rename from netbox/virtualization/search_indexes.py rename to netbox/virtualization/search.py index 6bb4121ff..a42ca1929 100644 --- a/netbox/virtualization/search_indexes.py +++ b/netbox/virtualization/search.py @@ -1,13 +1,14 @@ import virtualization.filtersets import virtualization.tables -from django.db import models +from dcim.models import Device from netbox.search.models import SearchMixin +from netbox.search import register_search from utilities.utils import count_related -from virtualization.models import Cluster, Device, VirtualMachine +from virtualization.models import Cluster, VirtualMachine +@register_search(Cluster) class ClusterIndex(SearchMixin): - model = Cluster queryset = Cluster.objects.prefetch_related('type', 'group').annotate( device_count=count_related(Device, 'cluster'), vm_count=count_related(VirtualMachine, 'cluster') ) @@ -17,8 +18,8 @@ class ClusterIndex(SearchMixin): choice_header = 'Virtualization' +@register_search(VirtualMachine) class VirtualMachineIndex(SearchMixin): - model = VirtualMachine queryset = VirtualMachine.objects.prefetch_related( 'cluster', 'tenant', @@ -31,9 +32,3 @@ class VirtualMachineIndex(SearchMixin): table = virtualization.tables.VirtualMachineTable url = 'virtualization:virtualmachine_list' choice_header = 'Virtualization' - - -VIRTUALIZATION_SEARCH_TYPES = { - 'cluster': ClusterIndex, - 'virtualmachine': VirtualMachineIndex, -} diff --git a/netbox/wireless/apps.py b/netbox/wireless/apps.py index 59e47aba5..51dee4188 100644 --- a/netbox/wireless/apps.py +++ b/netbox/wireless/apps.py @@ -5,4 +5,4 @@ class WirelessConfig(AppConfig): name = 'wireless' def ready(self): - import wireless.signals + from . import signals, search diff --git a/netbox/wireless/search_indexes.py b/netbox/wireless/search.py similarity index 83% rename from netbox/wireless/search_indexes.py rename to netbox/wireless/search.py index 60b9ab84a..a45244896 100644 --- a/netbox/wireless/search_indexes.py +++ b/netbox/wireless/search.py @@ -1,14 +1,14 @@ import wireless.filtersets import wireless.tables from dcim.models import Interface -from django.db import models from netbox.search.models import SearchMixin +from netbox.search import register_search from utilities.utils import count_related from wireless.models import WirelessLAN, WirelessLink +@register_search(WirelessLAN) class WirelessLANIndex(SearchMixin): - model = WirelessLAN queryset = WirelessLAN.objects.prefetch_related('group', 'vlan').annotate( interface_count=count_related(Interface, 'wireless_lans') ) @@ -18,16 +18,10 @@ class WirelessLANIndex(SearchMixin): choice_header = 'Wireless' +@register_search(WirelessLink) class WirelessLinkIndex(SearchMixin): - model = WirelessLink queryset = WirelessLink.objects.prefetch_related('interface_a__device', 'interface_b__device') filterset = wireless.filtersets.WirelessLinkFilterSet table = wireless.tables.WirelessLinkTable url = 'wireless:wirelesslink_list' choice_header = 'Wireless' - - -WIRELESS_SEARCH_TYPES = { - 'wirelesslan': WirelessLANIndex, - 'wirelesslink': WirelessLinkIndex, -}