1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Closes #10560: New global search (#10676)

* Initial work on new search backend

* Clean up search backends

* Return only the most relevant result per object

* Clear any pre-existing cached entries on cache()

* #6003: Implement global search functionality for custom field values

* Tweak field weights & document guidance

* Extend search() to accept a lookup type

* Move get_registry() out of SearchBackend

* Enforce object permissions when returning search results

* Add indexers for remaining models

* Avoid calling remove() on non-cacheable objects

* Use new search backend by default

* Extend search backend to filter by object type

* Clean up search view form

* Enable specifying lookup logic

* Add indexes for value field

* Remove object type selector from search bar

* Introduce SearchTable and enable HTMX for results

* Enable pagination

* Remove legacy search backend

* Cleanup

* Use a UUID for CachedValue primary key

* Refactoring search methods

* Define max search results limit

* Extend reindex command to support specifying particular models

* Add clear() and size to SearchBackend

* Optimize bulk caching performance

* Highlight matched portion of field value

* Performance improvements for reindexing

* Started on search tests

* Cleanup & docs

* Documentation updates

* Clean up SearchIndex

* Flatten search registry to register by app_label.model_name

* Clean up search backend classes

* Clean up RestrictedGenericForeignKey and RestrictedPrefetch

* Resolve migrations conflict
This commit is contained in:
Jeremy Stretch
2022-10-21 13:16:16 -04:00
committed by GitHub
parent 5d56d95fda
commit 9628dead07
50 changed files with 1579 additions and 675 deletions

View File

@@ -1,143 +1,293 @@
import dcim.filtersets
import dcim.tables
from dcim.models import (
Cable,
Device,
DeviceType,
Location,
Module,
ModuleType,
PowerFeed,
Rack,
RackReservation,
Site,
VirtualChassis,
)
from netbox.search import SearchIndex, register_search
from utilities.utils import count_related
from . import models
@register_search()
class SiteIndex(SearchIndex):
model = Site
queryset = Site.objects.prefetch_related('region', 'tenant', 'tenant__group')
filterset = dcim.filtersets.SiteFilterSet
table = dcim.tables.SiteTable
url = 'dcim:site_list'
@register_search()
class RackIndex(SearchIndex):
model = 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'
@register_search()
class RackReservationIndex(SearchIndex):
model = RackReservation
queryset = RackReservation.objects.prefetch_related('rack', 'user')
filterset = dcim.filtersets.RackReservationFilterSet
table = dcim.tables.RackReservationTable
url = 'dcim:rackreservation_list'
@register_search()
class LocationIndex(SearchIndex):
model = 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'
@register_search()
class DeviceTypeIndex(SearchIndex):
model = 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'
@register_search()
class DeviceIndex(SearchIndex):
model = 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'
@register_search()
class ModuleTypeIndex(SearchIndex):
model = 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'
@register_search()
class ModuleIndex(SearchIndex):
model = Module
queryset = Module.objects.prefetch_related(
'module_type__manufacturer',
'device',
'module_bay',
)
filterset = dcim.filtersets.ModuleFilterSet
table = dcim.tables.ModuleTable
url = 'dcim:module_list'
@register_search()
class VirtualChassisIndex(SearchIndex):
model = 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'
@register_search()
@register_search
class CableIndex(SearchIndex):
model = Cable
queryset = Cable.objects.all()
filterset = dcim.filtersets.CableFilterSet
table = dcim.tables.CableTable
url = 'dcim:cable_list'
model = models.Cable
fields = (
('label', 100),
)
@register_search()
@register_search
class ConsolePortIndex(SearchIndex):
model = models.ConsolePort
fields = (
('name', 100),
('label', 200),
('description', 500),
('speed', 2000),
)
@register_search
class ConsoleServerPortIndex(SearchIndex):
model = models.ConsoleServerPort
fields = (
('name', 100),
('label', 200),
('description', 500),
('speed', 2000),
)
@register_search
class DeviceIndex(SearchIndex):
model = models.Device
fields = (
('asset_tag', 50),
('serial', 60),
('name', 100),
('comments', 5000),
)
@register_search
class DeviceBayIndex(SearchIndex):
model = models.DeviceBay
fields = (
('name', 100),
('label', 200),
('description', 500),
)
@register_search
class DeviceRoleIndex(SearchIndex):
model = models.DeviceRole
fields = (
('name', 100),
('slug', 110),
('description', 500),
)
@register_search
class DeviceTypeIndex(SearchIndex):
model = models.DeviceType
fields = (
('model', 100),
('part_number', 200),
('comments', 5000),
)
@register_search
class FrontPortIndex(SearchIndex):
model = models.FrontPort
fields = (
('name', 100),
('label', 200),
('description', 500),
)
@register_search
class InterfaceIndex(SearchIndex):
model = models.Interface
fields = (
('name', 100),
('label', 200),
('mac_address', 300),
('wwn', 300),
('description', 500),
('mtu', 2000),
('speed', 2000),
)
@register_search
class InventoryItemIndex(SearchIndex):
model = models.InventoryItem
fields = (
('asset_tag', 50),
('serial', 60),
('name', 100),
('label', 200),
('description', 500),
('part_id', 2000),
)
@register_search
class LocationIndex(SearchIndex):
model = models.Location
fields = (
('name', 100),
('slug', 110),
('description', 500),
)
@register_search
class ManufacturerIndex(SearchIndex):
model = models.Manufacturer
fields = (
('name', 100),
('slug', 110),
('description', 500),
)
@register_search
class ModuleIndex(SearchIndex):
model = models.Module
fields = (
('asset_tag', 50),
('serial', 60),
('comments', 5000),
)
@register_search
class ModuleBayIndex(SearchIndex):
model = models.ModuleBay
fields = (
('name', 100),
('label', 200),
('description', 500),
)
@register_search
class ModuleTypeIndex(SearchIndex):
model = models.ModuleType
fields = (
('model', 100),
('part_number', 200),
('comments', 5000),
)
@register_search
class PlatformIndex(SearchIndex):
model = models.Platform
fields = (
('name', 100),
('slug', 110),
('napalm_driver', 300),
('description', 500),
)
@register_search
class PowerFeedIndex(SearchIndex):
model = PowerFeed
queryset = PowerFeed.objects.all()
filterset = dcim.filtersets.PowerFeedFilterSet
table = dcim.tables.PowerFeedTable
url = 'dcim:powerfeed_list'
model = models.PowerFeed
fields = (
('name', 100),
('comments', 5000),
)
@register_search
class PowerOutletIndex(SearchIndex):
model = models.PowerOutlet
fields = (
('name', 100),
('label', 200),
('description', 500),
)
@register_search
class PowerPanelIndex(SearchIndex):
model = models.PowerPanel
fields = (
('name', 100),
)
@register_search
class PowerPortIndex(SearchIndex):
model = models.PowerPort
fields = (
('name', 100),
('label', 200),
('description', 500),
('maximum_draw', 2000),
('allocated_draw', 2000),
)
@register_search
class RackIndex(SearchIndex):
model = models.Rack
fields = (
('asset_tag', 50),
('serial', 60),
('name', 100),
('facility_id', 200),
('comments', 5000),
)
@register_search
class RackReservationIndex(SearchIndex):
model = models.RackReservation
fields = (
('description', 500),
)
@register_search
class RackRoleIndex(SearchIndex):
model = models.RackRole
fields = (
('name', 100),
('slug', 110),
('description', 500),
)
@register_search
class RearPortIndex(SearchIndex):
model = models.RearPort
fields = (
('name', 100),
('label', 200),
('description', 500),
)
@register_search
class RegionIndex(SearchIndex):
model = models.Region
fields = (
('name', 100),
('slug', 110),
('description', 500)
)
@register_search
class SiteIndex(SearchIndex):
model = models.Site
fields = (
('name', 100),
('facility', 100),
('slug', 110),
('description', 500),
('physical_address', 2000),
('shipping_address', 2000),
('comments', 5000),
)
@register_search
class SiteGroupIndex(SearchIndex):
model = models.SiteGroup
fields = (
('name', 100),
('slug', 110),
('description', 500)
)
@register_search
class VirtualChassisIndex(SearchIndex):
model = models.VirtualChassis
fields = (
('name', 100),
('domain', 300)
)