mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-24 16:26:09 -06:00
Clean up search backend class
This commit is contained in:
parent
3750659c37
commit
325f4f1aa1
@ -17,28 +17,10 @@ class SearchEngineError(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class SearchBackend(object):
|
class SearchBackend:
|
||||||
"""A search engine capable of performing multi-table searches."""
|
"""A search engine capable of performing multi-table searches."""
|
||||||
_created_engines: dict = dict()
|
|
||||||
_search_choice_options = tuple()
|
_search_choice_options = tuple()
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_created_engines(cls):
|
|
||||||
"""Returns all created search engines."""
|
|
||||||
return list(cls._created_engines.items())
|
|
||||||
|
|
||||||
def __init__(self, engine_slug: str):
|
|
||||||
"""Initializes the search engine."""
|
|
||||||
# Check the slug is unique for this project.
|
|
||||||
if engine_slug in SearchBackend._created_engines:
|
|
||||||
raise SearchEngineError(f"A search engine has already been created with the slug {engine_slug}")
|
|
||||||
|
|
||||||
# Initialize this engine.
|
|
||||||
self._engine_slug = engine_slug
|
|
||||||
|
|
||||||
# Store a reference to this engine.
|
|
||||||
self.__class__._created_engines[engine_slug] = self
|
|
||||||
|
|
||||||
def get_registry(self):
|
def get_registry(self):
|
||||||
r = {}
|
r = {}
|
||||||
for app_label, models in registry['search'].items():
|
for app_label, models in registry['search'].items():
|
||||||
@ -47,6 +29,7 @@ class SearchBackend(object):
|
|||||||
return r
|
return r
|
||||||
|
|
||||||
def get_search_choices(self):
|
def get_search_choices(self):
|
||||||
|
"""Return the set of choices for individual object types, organized by category."""
|
||||||
if not self._search_choice_options:
|
if not self._search_choice_options:
|
||||||
|
|
||||||
# Organize choices by category
|
# Organize choices by category
|
||||||
@ -66,14 +49,21 @@ class SearchBackend(object):
|
|||||||
|
|
||||||
return self._search_choice_options
|
return self._search_choice_options
|
||||||
|
|
||||||
def search(self, request, search_text, models=(), exclude=(), ranking=True, backend_name=None):
|
def search(self, request, value, **kwargs):
|
||||||
"""Performs a search using the given text, returning a queryset of SearchEntry."""
|
"""Execute a search query for the given value."""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def cache(self, instance):
|
||||||
|
"""Create or update the cached copy of an instance."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
class FilterSetSearchBackend(SearchBackend):
|
class FilterSetSearchBackend(SearchBackend):
|
||||||
|
"""
|
||||||
def search(self, request, search_text):
|
Legacy search backend. Performs a discrete database query for each registered object type, using the FilterSet
|
||||||
|
class specified by the index for each.
|
||||||
|
"""
|
||||||
|
def search(self, request, value, **kwargs):
|
||||||
results = []
|
results = []
|
||||||
|
|
||||||
search_registry = self.get_registry()
|
search_registry = self.get_registry()
|
||||||
@ -97,7 +87,7 @@ class FilterSetSearchBackend(SearchBackend):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# Construct the results table for this object type
|
# Construct the results table for this object type
|
||||||
filtered_queryset = filterset({'q': search_text}, queryset=queryset).qs
|
filtered_queryset = filterset({'q': value}, queryset=queryset).qs
|
||||||
table = table(filtered_queryset, orderable=False)
|
table = table(filtered_queryset, orderable=False)
|
||||||
table.paginate(per_page=SEARCH_MAX_RESULTS)
|
table.paginate(per_page=SEARCH_MAX_RESULTS)
|
||||||
|
|
||||||
@ -105,36 +95,31 @@ class FilterSetSearchBackend(SearchBackend):
|
|||||||
results.append({
|
results.append({
|
||||||
'name': queryset.model._meta.verbose_name_plural,
|
'name': queryset.model._meta.verbose_name_plural,
|
||||||
'table': table,
|
'table': table,
|
||||||
'url': f"{reverse(url)}?q={search_text}"
|
'url': f"{reverse(url)}?q={value}"
|
||||||
})
|
})
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
def cache(self, instance):
|
||||||
|
# This backend does not utilize a cache
|
||||||
|
pass
|
||||||
|
|
||||||
def get_backend(backend_name=None):
|
|
||||||
"""Initializes and returns the search backend."""
|
|
||||||
global _backends_cache
|
|
||||||
if not backend_name:
|
|
||||||
backend_name = getattr(settings, "SEARCH_BACKEND", "netbox.search.backends.FilterSetSearchBackend")
|
|
||||||
|
|
||||||
# Try to use the cached backend.
|
def get_backend():
|
||||||
if backend_name in _backends_cache:
|
"""Initializes and returns the configured search backend."""
|
||||||
return _backends_cache[backend_name]
|
backend_name = settings.SEARCH_BACKEND
|
||||||
|
|
||||||
# Load the backend class.
|
# Load the backend class
|
||||||
backend_module_name, backend_cls_name = backend_name.rsplit(".", 1)
|
backend_module_name, backend_cls_name = backend_name.rsplit('.', 1)
|
||||||
backend_module = import_module(backend_module_name)
|
backend_module = import_module(backend_module_name)
|
||||||
try:
|
try:
|
||||||
backend_cls = getattr(backend_module, backend_cls_name)
|
backend_cls = getattr(backend_module, backend_cls_name)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise ImproperlyConfigured(f"Could not find a class named {backend_module_name} in {backend_cls_name}")
|
raise ImproperlyConfigured(f"Could not find a class named {backend_module_name} in {backend_cls_name}")
|
||||||
|
|
||||||
# Initialize the backend.
|
# Initialize and return the backend instance
|
||||||
backend = backend_cls("default")
|
return backend_cls()
|
||||||
_backends_cache[backend_name] = backend
|
|
||||||
return backend
|
|
||||||
|
|
||||||
|
|
||||||
# The main search methods.
|
|
||||||
default_search_engine = get_backend()
|
default_search_engine = get_backend()
|
||||||
search = default_search_engine.search
|
search = default_search_engine.search
|
||||||
|
@ -121,6 +121,7 @@ REMOTE_AUTH_GROUP_SEPARATOR = getattr(configuration, 'REMOTE_AUTH_GROUP_SEPARATO
|
|||||||
REPORTS_ROOT = getattr(configuration, 'REPORTS_ROOT', os.path.join(BASE_DIR, 'reports')).rstrip('/')
|
REPORTS_ROOT = getattr(configuration, 'REPORTS_ROOT', os.path.join(BASE_DIR, 'reports')).rstrip('/')
|
||||||
RQ_DEFAULT_TIMEOUT = getattr(configuration, 'RQ_DEFAULT_TIMEOUT', 300)
|
RQ_DEFAULT_TIMEOUT = getattr(configuration, 'RQ_DEFAULT_TIMEOUT', 300)
|
||||||
SCRIPTS_ROOT = getattr(configuration, 'SCRIPTS_ROOT', os.path.join(BASE_DIR, 'scripts')).rstrip('/')
|
SCRIPTS_ROOT = getattr(configuration, 'SCRIPTS_ROOT', os.path.join(BASE_DIR, 'scripts')).rstrip('/')
|
||||||
|
SEARCH_BACKEND = getattr(configuration, 'SEARCH_BACKEND', 'netbox.search.backends.FilterSetSearchBackend')
|
||||||
SENTRY_DSN = getattr(configuration, 'SENTRY_DSN', DEFAULT_SENTRY_DSN)
|
SENTRY_DSN = getattr(configuration, 'SENTRY_DSN', DEFAULT_SENTRY_DSN)
|
||||||
SENTRY_ENABLED = getattr(configuration, 'SENTRY_ENABLED', False)
|
SENTRY_ENABLED = getattr(configuration, 'SENTRY_ENABLED', False)
|
||||||
SENTRY_SAMPLE_RATE = getattr(configuration, 'SENTRY_SAMPLE_RATE', 1.0)
|
SENTRY_SAMPLE_RATE = getattr(configuration, 'SENTRY_SAMPLE_RATE', 1.0)
|
||||||
|
Loading…
Reference in New Issue
Block a user