Closes #21300: Cache model-specific custom field lookups for the duration of a request (#21334)

This commit is contained in:
Jeremy Stretch
2026-02-02 13:58:12 -05:00
committed by GitHub
parent 96f0debe6e
commit c060eef1d8
10 changed files with 64 additions and 52 deletions

View File

@@ -4,7 +4,6 @@ from drf_spectacular.utils import extend_schema_field
from rest_framework.fields import Field
from rest_framework.serializers import ValidationError
from core.models import ObjectType
from extras.choices import CustomFieldTypeChoices
from extras.constants import CUSTOMFIELD_EMPTY_VALUES
from extras.models import CustomField
@@ -24,13 +23,9 @@ class CustomFieldDefaultValues:
def __call__(self, serializer_field):
self.model = serializer_field.parent.Meta.model
# Retrieve the CustomFields for the parent model
object_type = ObjectType.objects.get_for_model(self.model)
fields = CustomField.objects.filter(object_types=object_type)
# Populate the default value for each CustomField
# Populate the default value for each CustomField on the model
value = {}
for field in fields:
for field in CustomField.objects.get_for_model(self.model):
if field.default is not None:
value[field.name] = field.default
else:
@@ -47,8 +42,7 @@ class CustomFieldsDataField(Field):
Cache CustomFields assigned to this model to avoid redundant database queries
"""
if not hasattr(self, '_custom_fields'):
object_type = ObjectType.objects.get_for_model(self.parent.Meta.model)
self._custom_fields = CustomField.objects.filter(object_types=object_type)
self._custom_fields = CustomField.objects.get_for_model(self.parent.Meta.model)
return self._custom_fields
def to_representation(self, obj):

View File

@@ -19,6 +19,7 @@ from django.utils.translation import gettext_lazy as _
from core.models import ObjectType
from extras.choices import *
from extras.data import CHOICE_SETS
from netbox.context import query_cache
from netbox.models import ChangeLoggedModel
from netbox.models.features import CloningMixin, ExportTemplatesMixin
from netbox.models.mixins import OwnerMixin
@@ -58,8 +59,20 @@ class CustomFieldManager(models.Manager.from_queryset(RestrictedQuerySet)):
"""
Return all CustomFields assigned to the given model.
"""
# Check the request cache before hitting the database
cache = query_cache.get()
if cache is not None:
if custom_fields := cache['custom_fields'].get(model._meta.model):
return custom_fields
content_type = ObjectType.objects.get_for_model(model._meta.concrete_model)
return self.get_queryset().filter(object_types=content_type)
custom_fields = self.get_queryset().filter(object_types=content_type)
# Populate the request cache to avoid redundant lookups
if cache is not None:
cache['custom_fields'][model._meta.model] = custom_fields
return custom_fields
def get_defaults_for_model(self, model):
"""