Skip to content

Commit 3ec10a5

Browse files
committed
Fix N+1 issue in ops-learning
1 parent 225c744 commit 3ec10a5

3 files changed

Lines changed: 48 additions & 14 deletions

File tree

assets

per/drf_views.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from rest_framework.response import Response
2121
from rest_framework.settings import api_settings
2222

23-
from api.models import Country, Region
23+
from api.models import AppealDocument, Country, Region
2424
from deployments.models import SectorTag
2525
from main.permissions import DenyGuestUserMutationPermission, DenyGuestUserPermission
2626
from main.utils import SpreadSheetContentNegotiation
@@ -1202,6 +1202,7 @@ def get_queryset(self):
12021202
return qs.select_related(
12031203
"appeal_code",
12041204
).prefetch_related(
1205+
"appeal_code__event__appeals",
12051206
"sector",
12061207
"sector_validated",
12071208
"organization",
@@ -1216,6 +1217,7 @@ def get_queryset(self):
12161217
"appeal_code",
12171218
)
12181219
.prefetch_related(
1220+
"appeal_code__event__appeals",
12191221
"sector",
12201222
"sector_validated",
12211223
"organization",
@@ -1226,6 +1228,26 @@ def get_queryset(self):
12261228
)
12271229
)
12281230

1231+
def get_serializer_context(self):
1232+
context = super().get_serializer_context()
1233+
if getattr(self, "swagger_fake_view", False):
1234+
return context
1235+
view_action = getattr(self, "action", None)
1236+
if view_action == "list":
1237+
queryset = self.filter_queryset(self.get_queryset())
1238+
appeal_document_ids = list(
1239+
queryset.exclude(appeal_document_id__isnull=True).values_list("appeal_document_id", flat=True).distinct()
1240+
)
1241+
if appeal_document_ids:
1242+
context["appeal_documents_map"] = AppealDocument.objects.in_bulk(appeal_document_ids)
1243+
elif view_action == "retrieve":
1244+
lookup_kwarg = self.lookup_url_kwarg or self.lookup_field
1245+
if lookup_kwarg in self.kwargs:
1246+
obj = self.get_object()
1247+
if obj.appeal_document_id:
1248+
context["appeal_documents_map"] = AppealDocument.objects.in_bulk([obj.appeal_document_id])
1249+
return context
1250+
12291251
def get_serializer_class(self):
12301252
if self.request.method == "GET":
12311253
request_format = self.request.GET.get("format", "json")

per/serializers.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,14 +1054,20 @@ class Meta:
10541054
fields = "__all__"
10551055
read_only_fields = ("created_at", "modified_at")
10561056

1057-
@staticmethod
1058-
def get_document_url(obj):
1059-
if obj.appeal_document_id and (document := AppealDocument.objects.filter(id=obj.appeal_document_id).first()):
1057+
def _get_document(self, obj):
1058+
if not obj.appeal_document_id:
1059+
return None
1060+
document_map = self.context.get("appeal_documents_map")
1061+
if document_map is not None:
1062+
return document_map.get(obj.appeal_document_id)
1063+
return AppealDocument.objects.filter(id=obj.appeal_document_id).first()
1064+
1065+
def get_document_url(self, obj):
1066+
if document := self._get_document(obj):
10601067
return document.document_url
10611068

1062-
@staticmethod
1063-
def get_document_name(obj):
1064-
if obj.appeal_document_id and (document := AppealDocument.objects.filter(id=obj.appeal_document_id).first()):
1069+
def get_document_name(self, obj):
1070+
if document := self._get_document(obj):
10651071
return document.name
10661072

10671073

@@ -1088,14 +1094,20 @@ class Meta:
10881094
)
10891095
exclude = ("learning", "type", "organization", "sector", "per_component")
10901096

1091-
@staticmethod
1092-
def get_document_url(obj):
1093-
if obj.appeal_document_id and (document := AppealDocument.objects.filter(id=obj.appeal_document_id).first()):
1097+
def _get_document(self, obj):
1098+
if not obj.appeal_document_id:
1099+
return None
1100+
document_map = self.context.get("appeal_documents_map")
1101+
if document_map is not None:
1102+
return document_map.get(obj.appeal_document_id)
1103+
return AppealDocument.objects.filter(id=obj.appeal_document_id).first()
1104+
1105+
def get_document_url(self, obj):
1106+
if document := self._get_document(obj):
10941107
return document.document_url
10951108

1096-
@staticmethod
1097-
def get_document_name(obj):
1098-
if obj.appeal_document_id and (document := AppealDocument.objects.filter(id=obj.appeal_document_id).first()):
1109+
def get_document_name(self, obj):
1110+
if document := self._get_document(obj):
10991111
return document.name
11001112

11011113

0 commit comments

Comments
 (0)