Преглед изворни кода

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
Andrey Tikhonov пре 9 месеци
родитељ
комит
145ee11a3f
2 измењених фајлова са 16 додато и 2 уклоњено
  1. 1 0
      netbox/dcim/api/views.py
  2. 15 2
      netbox/ipam/api/views.py

+ 1 - 0
netbox/dcim/api/views.py

@@ -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()

+ 15 - 2
netbox/ipam/api/views.py

@@ -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