diff --git a/netbox/circuits/search_indexes.py b/netbox/circuits/search_indexes.py index 91cc291da..a1fa7897f 100644 --- a/netbox/circuits/search_indexes.py +++ b/netbox/circuits/search_indexes.py @@ -1,14 +1,15 @@ -import dcim.filtersets -import dcim.tables +import circuits.filtersets +import circuits.tables from circuits.models import Circuit, Provider, ProviderNetwork from django.db import models from search.models import SearchMixin +from utilities.utils import count_related class ProviderIndex(SearchMixin): def __init__(self): self.model = Provider - self.queryset = (Provider.objects.annotate(count_circuits=count_related(Circuit, 'provider')),) + self.queryset = Provider.objects.annotate(count_circuits=count_related(Circuit, 'provider')) self.filterset = circuits.filtersets.ProviderFilterSet self.table = circuits.tables.ProviderTable self.url = 'circuits:provider_list' diff --git a/netbox/dcim/search_indexes.py b/netbox/dcim/search_indexes.py index b95768c79..15f30e827 100644 --- a/netbox/dcim/search_indexes.py +++ b/netbox/dcim/search_indexes.py @@ -16,6 +16,7 @@ from dcim.models import ( ) from django.db import models from search.models import SearchMixin +from utilities.utils import count_related class SiteIndex(SearchMixin): diff --git a/netbox/extras/search_indexes.py b/netbox/extras/search_indexes.py index 8e69fc160..087aab8bb 100644 --- a/netbox/extras/search_indexes.py +++ b/netbox/extras/search_indexes.py @@ -1,8 +1,9 @@ -import dcim.filtersets -import dcim.tables +import extras.filtersets +import extras.tables from django.db import models from extras.models import JournalEntry from search.models import SearchMixin +from utilities.utils import count_related class JournalEntryIndex(SearchMixin): diff --git a/netbox/ipam/search_indexes.py b/netbox/ipam/search_indexes.py index 274e603eb..535656f58 100644 --- a/netbox/ipam/search_indexes.py +++ b/netbox/ipam/search_indexes.py @@ -1,8 +1,9 @@ -import dcim.filtersets -import dcim.tables +import ipam.filtersets +import ipam.tables from django.db import models from ipam.models import ASN, VLAN, VRF, Aggregate, IPAddress, Prefix, Service from search.models import SearchMixin +from utilities.utils import count_related class VRFIndex(SearchMixin): diff --git a/netbox/netbox/forms/__init__.py b/netbox/netbox/forms/__init__.py index d1451e003..50cc6964d 100644 --- a/netbox/netbox/forms/__init__.py +++ b/netbox/netbox/forms/__init__.py @@ -1,7 +1,8 @@ from django import forms +from utilities.forms import BootstrapMixin from netbox.search import SEARCH_TYPE_HIERARCHY -from utilities.forms import BootstrapMixin + from .base import * @@ -11,7 +12,7 @@ def build_search_choices(): for category, items in SEARCH_TYPE_HIERARCHY.items(): subcategories = list() for slug, obj in items.items(): - name = obj['queryset'].model._meta.verbose_name_plural + name = obj.queryset.model._meta.verbose_name_plural name = name[0].upper() + name[1:] subcategories.append((slug, name)) result.append((category, tuple(subcategories))) @@ -36,10 +37,6 @@ def build_options(): class SearchForm(BootstrapMixin, forms.Form): - q = forms.CharField( - label='Search' - ) - obj_type = forms.ChoiceField( - choices=OBJ_TYPE_CHOICES, required=False, label='Type' - ) + q = forms.CharField(label='Search') + obj_type = forms.ChoiceField(choices=OBJ_TYPE_CHOICES, required=False, label='Type') options = build_options() diff --git a/netbox/netbox/search.py b/netbox/netbox/search.py index 6d1c5d4a3..4a1e2e278 100644 --- a/netbox/netbox/search.py +++ b/netbox/netbox/search.py @@ -1,263 +1,19 @@ -import circuits.filtersets -import circuits.tables -import dcim.filtersets -import dcim.tables -import extras.filtersets -import extras.tables -import ipam.filtersets -import ipam.tables -import tenancy.filtersets -import tenancy.tables -import virtualization.filtersets -import wireless.tables -import wireless.filtersets -import virtualization.tables -from circuits.models import Circuit, ProviderNetwork, Provider -from dcim.models import ( - Cable, Device, DeviceType, Interface, Location, Module, ModuleType, PowerFeed, Rack, RackReservation, Site, - VirtualChassis, -) -from extras.models import JournalEntry -from ipam.models import Aggregate, ASN, IPAddress, Prefix, Service, VLAN, VRF -from tenancy.models import Contact, Tenant, ContactAssignment -from utilities.utils import count_related -from wireless.models import WirelessLAN, WirelessLink -from virtualization.models import Cluster, VirtualMachine - -CIRCUIT_TYPES = { - 'provider': { - 'queryset': Provider.objects.annotate( - count_circuits=count_related(Circuit, 'provider') - ), - 'filterset': circuits.filtersets.ProviderFilterSet, - 'table': circuits.tables.ProviderTable, - 'url': 'circuits:provider_list', - }, - 'circuit': { - 'queryset': Circuit.objects.prefetch_related( - 'type', 'provider', 'tenant', 'tenant__group', 'terminations__site' - ), - 'filterset': circuits.filtersets.CircuitFilterSet, - 'table': circuits.tables.CircuitTable, - 'url': 'circuits:circuit_list', - }, - 'providernetwork': { - 'queryset': ProviderNetwork.objects.prefetch_related('provider'), - 'filterset': circuits.filtersets.ProviderNetworkFilterSet, - 'table': circuits.tables.ProviderNetworkTable, - 'url': 'circuits:providernetwork_list', - }, -} - -DCIM_TYPES = { - 'site': { - 'queryset': Site.objects.prefetch_related('region', 'tenant', 'tenant__group'), - 'filterset': dcim.filtersets.SiteFilterSet, - 'table': dcim.tables.SiteTable, - 'url': 'dcim:site_list', - }, - 'rack': { - 'queryset': Rack.objects.prefetch_related('site', 'location', 'tenant', 'tenant__group', 'role').annotate( - device_count=count_related(Device, 'rack') - ), - 'filterset': dcim.filtersets.RackFilterSet, - 'table': dcim.tables.RackTable, - 'url': 'dcim:rack_list', - }, - 'rackreservation': { - 'queryset': RackReservation.objects.prefetch_related('rack', 'user'), - 'filterset': dcim.filtersets.RackReservationFilterSet, - 'table': dcim.tables.RackReservationTable, - 'url': 'dcim:rackreservation_list', - }, - 'location': { - 'queryset': Location.objects.add_related_count( - Location.objects.add_related_count( - Location.objects.all(), - Device, - 'location', - 'device_count', - cumulative=True - ), - Rack, - 'location', - 'rack_count', - cumulative=True - ).prefetch_related('site'), - 'filterset': dcim.filtersets.LocationFilterSet, - 'table': dcim.tables.LocationTable, - 'url': 'dcim:location_list', - }, - 'devicetype': { - 'queryset': DeviceType.objects.prefetch_related('manufacturer').annotate( - instance_count=count_related(Device, 'device_type') - ), - 'filterset': dcim.filtersets.DeviceTypeFilterSet, - 'table': dcim.tables.DeviceTypeTable, - 'url': 'dcim:devicetype_list', - }, - 'device': { - 'queryset': Device.objects.prefetch_related( - 'device_type__manufacturer', 'device_role', 'tenant', 'tenant__group', 'site', 'rack', 'primary_ip4', - 'primary_ip6', - ), - 'filterset': dcim.filtersets.DeviceFilterSet, - 'table': dcim.tables.DeviceTable, - 'url': 'dcim:device_list', - }, - 'moduletype': { - 'queryset': ModuleType.objects.prefetch_related('manufacturer').annotate( - instance_count=count_related(Module, 'module_type') - ), - 'filterset': dcim.filtersets.ModuleTypeFilterSet, - 'table': dcim.tables.ModuleTypeTable, - 'url': 'dcim:moduletype_list', - }, - 'module': { - 'queryset': Module.objects.prefetch_related( - 'module_type__manufacturer', 'device', 'module_bay', - ), - 'filterset': dcim.filtersets.ModuleFilterSet, - 'table': dcim.tables.ModuleTable, - 'url': 'dcim:module_list', - }, - 'virtualchassis': { - 'queryset': VirtualChassis.objects.prefetch_related('master').annotate( - member_count=count_related(Device, 'virtual_chassis') - ), - 'filterset': dcim.filtersets.VirtualChassisFilterSet, - 'table': dcim.tables.VirtualChassisTable, - 'url': 'dcim:virtualchassis_list', - }, - 'cable': { - 'queryset': Cable.objects.all(), - 'filterset': dcim.filtersets.CableFilterSet, - 'table': dcim.tables.CableTable, - 'url': 'dcim:cable_list', - }, - 'powerfeed': { - 'queryset': PowerFeed.objects.all(), - 'filterset': dcim.filtersets.PowerFeedFilterSet, - 'table': dcim.tables.PowerFeedTable, - 'url': 'dcim:powerfeed_list', - }, -} - -IPAM_TYPES = { - 'vrf': { - 'queryset': VRF.objects.prefetch_related('tenant', 'tenant__group'), - 'filterset': ipam.filtersets.VRFFilterSet, - 'table': ipam.tables.VRFTable, - 'url': 'ipam:vrf_list', - }, - 'aggregate': { - 'queryset': Aggregate.objects.prefetch_related('rir'), - 'filterset': ipam.filtersets.AggregateFilterSet, - 'table': ipam.tables.AggregateTable, - 'url': 'ipam:aggregate_list', - }, - 'prefix': { - 'queryset': Prefix.objects.prefetch_related('site', 'vrf__tenant', 'tenant', 'tenant__group', 'vlan', 'role'), - 'filterset': ipam.filtersets.PrefixFilterSet, - 'table': ipam.tables.PrefixTable, - 'url': 'ipam:prefix_list', - }, - 'ipaddress': { - 'queryset': IPAddress.objects.prefetch_related('vrf__tenant', 'tenant', 'tenant__group'), - 'filterset': ipam.filtersets.IPAddressFilterSet, - 'table': ipam.tables.IPAddressTable, - 'url': 'ipam:ipaddress_list', - }, - 'vlan': { - 'queryset': VLAN.objects.prefetch_related('site', 'group', 'tenant', 'tenant__group', 'role'), - 'filterset': ipam.filtersets.VLANFilterSet, - 'table': ipam.tables.VLANTable, - 'url': 'ipam:vlan_list', - }, - 'asn': { - 'queryset': ASN.objects.prefetch_related('rir', 'tenant', 'tenant__group'), - 'filterset': ipam.filtersets.ASNFilterSet, - 'table': ipam.tables.ASNTable, - 'url': 'ipam:asn_list', - }, - 'service': { - 'queryset': Service.objects.prefetch_related('device', 'virtual_machine'), - 'filterset': ipam.filtersets.ServiceFilterSet, - 'table': ipam.tables.ServiceTable, - 'url': 'ipam:service_list', - }, -} - -TENANCY_TYPES = { - 'tenant': { - 'queryset': Tenant.objects.prefetch_related('group'), - 'filterset': tenancy.filtersets.TenantFilterSet, - 'table': tenancy.tables.TenantTable, - 'url': 'tenancy:tenant_list', - }, - 'contact': { - 'queryset': Contact.objects.prefetch_related('group', 'assignments').annotate( - assignment_count=count_related(ContactAssignment, 'contact')), - 'filterset': tenancy.filtersets.ContactFilterSet, - 'table': tenancy.tables.ContactTable, - 'url': 'tenancy:contact_list', - }, -} - -VIRTUALIZATION_TYPES = { - 'cluster': { - 'queryset': Cluster.objects.prefetch_related('type', 'group').annotate( - device_count=count_related(Device, 'cluster'), - vm_count=count_related(VirtualMachine, 'cluster') - ), - 'filterset': virtualization.filtersets.ClusterFilterSet, - 'table': virtualization.tables.ClusterTable, - 'url': 'virtualization:cluster_list', - }, - 'virtualmachine': { - 'queryset': VirtualMachine.objects.prefetch_related( - 'cluster', 'tenant', 'tenant__group', 'platform', 'primary_ip4', 'primary_ip6', - ), - 'filterset': virtualization.filtersets.VirtualMachineFilterSet, - 'table': virtualization.tables.VirtualMachineTable, - 'url': 'virtualization:virtualmachine_list', - }, -} - -WIRELESS_TYPES = { - 'wirelesslan': { - 'queryset': WirelessLAN.objects.prefetch_related('group', 'vlan').annotate( - interface_count=count_related(Interface, 'wireless_lans') - ), - 'filterset': wireless.filtersets.WirelessLANFilterSet, - 'table': wireless.tables.WirelessLANTable, - 'url': 'wireless:wirelesslan_list', - }, - 'wirelesslink': { - 'queryset': WirelessLink.objects.prefetch_related('interface_a__device', 'interface_b__device'), - 'filterset': wireless.filtersets.WirelessLinkFilterSet, - 'table': wireless.tables.WirelessLinkTable, - 'url': 'wireless:wirelesslink_list', - }, -} - -JOURNAL_TYPES = { - 'journalentry': { - 'queryset': JournalEntry.objects.prefetch_related('assigned_object', 'created_by'), - 'filterset': extras.filtersets.JournalEntryFilterSet, - 'table': extras.tables.JournalEntryTable, - 'url': 'extras:journalentry_list', - }, -} +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_TYPES, - 'DCIM': DCIM_TYPES, - 'IPAM': IPAM_TYPES, - 'Tenancy': TENANCY_TYPES, - 'Virtualization': VIRTUALIZATION_TYPES, - 'Wireless': WIRELESS_TYPES, - 'Journal': JOURNAL_TYPES, + '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, } diff --git a/netbox/tenancy/search_indexes.py b/netbox/tenancy/search_indexes.py index 4e73b8d25..423e15ff9 100644 --- a/netbox/tenancy/search_indexes.py +++ b/netbox/tenancy/search_indexes.py @@ -1,8 +1,9 @@ -import dcim.filtersets -import dcim.tables +import tenancy.filtersets +import tenancy.tables from django.db import models from search.models import SearchMixin -from tenancy.models import Contact, Tenant +from tenancy.models import Contact, ContactAssignment, Tenant +from utilities.utils import count_related class TenantIndex(SearchMixin): @@ -26,6 +27,6 @@ class ContactIndex(SearchMixin): TENANCY_SEARCH_TYPES = { - 'tenant': TenancyIndex(), + 'tenant': TenantIndex(), 'contact': ContactIndex(), } diff --git a/netbox/virtualization/search_indexes.py b/netbox/virtualization/search_indexes.py index 14d89f830..ef8839c12 100644 --- a/netbox/virtualization/search_indexes.py +++ b/netbox/virtualization/search_indexes.py @@ -1,21 +1,9 @@ -import dcim.filtersets -import dcim.tables -from dcim.models import ( - Cable, - Device, - DeviceType, - Interface, - Location, - Module, - ModuleType, - PowerFeed, - Rack, - RackReservation, - Site, - VirtualChassis, -) +import virtualization.filtersets +import virtualization.tables from django.db import models from search.models import SearchMixin +from utilities.utils import count_related +from virtualization.models import Cluster, Device, VirtualMachine class ClusterIndex(SearchMixin): diff --git a/netbox/wireless/search_indexes.py b/netbox/wireless/search_indexes.py index 1321e11bc..99a3d3610 100644 --- a/netbox/wireless/search_indexes.py +++ b/netbox/wireless/search_indexes.py @@ -1,7 +1,9 @@ -import dcim.filtersets -import dcim.tables +import wireless.filtersets +import wireless.tables +from dcim.models import Interface from django.db import models from search.models import SearchMixin +from utilities.utils import count_related from wireless.models import WirelessLAN, WirelessLink