Fixes #19309: N+1 problem on /interfaces, /ip-addresses and /prefixes requests (#19304)

* Fixes N+1 problem on /interfaces, /ip-addresses and /prefixes requests

* remove extra .all()

* more prefetch for IPAddressViewSet
This commit is contained in:
Andrey Tikhonov 2025-05-06 18:47:44 +02:00 committed by GitHub
parent 94618a9dfb
commit 145ee11a3f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 16 additions and 2 deletions

View File

@ -461,6 +461,7 @@ class InterfaceViewSet(PathEndpointMixin, NetBoxModelViewSet):
Interface.objects.select_related("device", "cable"), Interface.objects.select_related("device", "cable"),
], ],
), ),
'virtual_circuit_termination',
'l2vpn_terminations', # Referenced by InterfaceSerializer.l2vpn_termination 'l2vpn_terminations', # Referenced by InterfaceSerializer.l2vpn_termination
'ip_addresses', # Referenced by Interface.count_ipaddresses() 'ip_addresses', # Referenced by Interface.count_ipaddresses()
'fhrp_group_assignments', # Referenced by Interface.count_fhrp_groups() 'fhrp_group_assignments', # Referenced by Interface.count_fhrp_groups()

View File

@ -1,5 +1,6 @@
from copy import deepcopy from copy import deepcopy
from django.contrib.contenttypes.prefetch import GenericPrefetch
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.db import transaction from django.db import transaction
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
@ -13,6 +14,7 @@ from rest_framework.response import Response
from rest_framework.routers import APIRootView from rest_framework.routers import APIRootView
from rest_framework.views import APIView from rest_framework.views import APIView
from dcim.models import Interface
from ipam import filtersets from ipam import filtersets
from ipam.models import * from ipam.models import *
from ipam.utils import get_next_available_prefix from ipam.utils import get_next_available_prefix
@ -21,6 +23,7 @@ from netbox.api.viewsets.mixins import ObjectValidationMixin
from netbox.config import get_config from netbox.config import get_config
from netbox.constants import ADVISORY_LOCK_KEYS from netbox.constants import ADVISORY_LOCK_KEYS
from utilities.api import get_serializer_for_model from utilities.api import get_serializer_for_model
from virtualization.models import VMInterface
from . import serializers from . import serializers
@ -79,7 +82,7 @@ class RoleViewSet(NetBoxModelViewSet):
class PrefixViewSet(NetBoxModelViewSet): class PrefixViewSet(NetBoxModelViewSet):
queryset = Prefix.objects.all() queryset = Prefix.objects.prefetch_related("scope")
serializer_class = serializers.PrefixSerializer serializer_class = serializers.PrefixSerializer
filterset_class = filtersets.PrefixFilterSet filterset_class = filtersets.PrefixFilterSet
@ -100,7 +103,17 @@ class IPRangeViewSet(NetBoxModelViewSet):
class IPAddressViewSet(NetBoxModelViewSet): class IPAddressViewSet(NetBoxModelViewSet):
queryset = IPAddress.objects.all() queryset = IPAddress.objects.prefetch_related(
GenericPrefetch(
"assigned_object",
[
# serializers are taken according to IPADDRESS_ASSIGNMENT_MODELS
FHRPGroup.objects.all(),
Interface.objects.select_related("cable", "device"),
VMInterface.objects.select_related("virtual_machine"),
],
),
)
serializer_class = serializers.IPAddressSerializer serializer_class = serializers.IPAddressSerializer
filterset_class = filtersets.IPAddressFilterSet filterset_class = filtersets.IPAddressFilterSet