diff --git a/netbox/core/models/object_types.py b/netbox/core/models/object_types.py index 21fbde3b3..1daeb2c4b 100644 --- a/netbox/core/models/object_types.py +++ b/netbox/core/models/object_types.py @@ -9,6 +9,7 @@ from django.db import connection, models from django.db.models import Q from django.utils.translation import gettext as _ +from netbox.context import query_cache from netbox.plugins import PluginConfig from netbox.registry import registry from utilities.string import title @@ -70,6 +71,12 @@ class ObjectTypeManager(models.Manager): """ from netbox.models.features import get_model_features, model_is_public + # Check the request cache before hitting the database + cache = query_cache.get() + if cache is not None: + if ot := cache['object_types'].get((model._meta.model, for_concrete_model)): + return ot + # TODO: Remove this in NetBox v5.0 # If the ObjectType table has not yet been provisioned (e.g. because we're in a pre-v4.4 migration), # fall back to ContentType. @@ -96,6 +103,10 @@ class ObjectTypeManager(models.Manager): features=get_model_features(model), )[0] + # Populate the request cache to avoid redundant lookups + if cache is not None: + cache['object_types'][(model._meta.model, for_concrete_model)] = ot + return ot def get_for_models(self, *models, for_concrete_models=True): diff --git a/netbox/netbox/context.py b/netbox/netbox/context.py index 744c36df4..78cad2176 100644 --- a/netbox/netbox/context.py +++ b/netbox/netbox/context.py @@ -3,8 +3,10 @@ from contextvars import ContextVar __all__ = ( 'current_request', 'events_queue', + 'query_cache', ) current_request = ContextVar('current_request', default=None) events_queue = ContextVar('events_queue', default=dict()) +query_cache = ContextVar('query_cache', default=None) diff --git a/netbox/netbox/context_managers.py b/netbox/netbox/context_managers.py index 7b01cce94..1d2ff61a2 100644 --- a/netbox/netbox/context_managers.py +++ b/netbox/netbox/context_managers.py @@ -1,6 +1,7 @@ +from collections import defaultdict from contextlib import contextmanager -from netbox.context import current_request, events_queue +from netbox.context import current_request, events_queue, query_cache from netbox.utils import register_request_processor from extras.events import flush_events @@ -16,6 +17,7 @@ def event_tracking(request): """ current_request.set(request) events_queue.set({}) + query_cache.set(defaultdict(dict)) yield @@ -26,3 +28,4 @@ def event_tracking(request): # Clear context vars current_request.set(None) events_queue.set({}) + query_cache.set(None)