Skip to content

Commit c116213

Browse files
committed
Fix Active Dref Operations List n+1 query issue (active-dref)
1 parent 61b8481 commit c116213

2 files changed

Lines changed: 54 additions & 12 deletions

File tree

dref/serializers.py

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -252,24 +252,36 @@ class Meta:
252252

253253
@extend_schema_field(MiniOperationalUpdateActiveSerializer(many=True))
254254
def get_operational_update_details(self, obj):
255-
queryset = DrefOperationalUpdate.objects.filter(dref_id=obj.id).order_by("-created_at")
255+
prefetched = getattr(obj, "prefetched_operational_updates", None)
256+
queryset = prefetched if prefetched is not None else obj.drefoperationalupdate_set.order_by("-created_at")
256257
return MiniOperationalUpdateActiveSerializer(queryset, many=True).data
257258

258259
@extend_schema_field(MiniDrefFinalReportActiveSerializer)
259260
def get_final_report_details(self, obj):
260-
queryset = DrefFinalReport.objects.filter(dref_id=obj.id).first()
261-
return MiniDrefFinalReportActiveSerializer(queryset).data
261+
prefetched = getattr(obj, "prefetched_final_report", None)
262+
if prefetched is not None:
263+
final_report = prefetched[0] if prefetched else None
264+
else:
265+
try:
266+
final_report = obj.dreffinalreport
267+
except DrefFinalReport.DoesNotExist:
268+
final_report = None
269+
return MiniDrefFinalReportActiveSerializer(final_report).data
262270

263271
def get_has_ops_update(self, obj) -> bool:
264-
op_count_count = obj.drefoperationalupdate_set.count()
265-
if op_count_count > 0:
266-
return True
267-
return False
272+
prefetched = getattr(obj, "prefetched_operational_updates", None)
273+
if prefetched is not None:
274+
return len(prefetched) > 0
275+
return obj.drefoperationalupdate_set.exists()
268276

269277
def get_has_final_report(self, obj) -> bool:
270-
if hasattr(obj, "dreffinalreport"):
271-
return True
272-
return False
278+
prefetched = getattr(obj, "prefetched_final_report", None)
279+
if prefetched is not None:
280+
return bool(prefetched)
281+
try:
282+
return obj.dreffinalreport is not None
283+
except DrefFinalReport.DoesNotExist:
284+
return False
273285

274286
def get_application_type(self, obj) -> str:
275287
return "DREF"
@@ -278,10 +290,23 @@ def get_application_type_display(self, obj) -> str:
278290
return gettext("DREF application")
279291

280292
def get_unpublished_op_update_count(self, obj) -> int:
293+
prefetched = getattr(obj, "prefetched_operational_updates", None)
294+
if prefetched is not None:
295+
return sum(1 for op in prefetched if op.status != Dref.Status.APPROVED)
281296
return DrefOperationalUpdate.objects.filter(dref_id=obj.id).exclude(status=Dref.Status.APPROVED).count()
282297

283298
def get_unpublished_final_report_count(self, obj) -> int:
284-
return DrefFinalReport.objects.filter(dref_id=obj.id).exclude(status=Dref.Status.APPROVED).count()
299+
prefetched = getattr(obj, "prefetched_final_report", None)
300+
if prefetched is not None:
301+
if not prefetched:
302+
return 0
303+
final_report = prefetched[0]
304+
return 0 if final_report.status == Dref.Status.APPROVED else 1
305+
try:
306+
final_report = obj.dreffinalreport
307+
except DrefFinalReport.DoesNotExist:
308+
return 0
309+
return 0 if final_report.status == Dref.Status.APPROVED else 1
285310

286311

287312
class PlannedInterventionSerializer(

dref/views.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import django.utils.timezone as timezone
66
from django.contrib.auth.models import Permission
77
from django.db import models, transaction
8+
from django.db.models import Prefetch
89
from django.http import HttpResponse
910
from django.templatetags.static import static
1011
from django.utils.translation import gettext
@@ -345,7 +346,23 @@ class ActiveDrefOperationsViewSet(viewsets.ReadOnlyModelViewSet):
345346
permission_classes = [permissions.IsAuthenticated, DenyGuestUserPermission]
346347
filterset_class = ActiveDrefFilterSet
347348
queryset = (
348-
Dref.objects.prefetch_related("planned_interventions", "needs_identified", "national_society_actions", "users")
349+
Dref.objects.select_related("country")
350+
.prefetch_related(
351+
"planned_interventions",
352+
"needs_identified",
353+
"national_society_actions",
354+
"users",
355+
Prefetch(
356+
"dreffinalreport",
357+
queryset=DrefFinalReport.objects.all(),
358+
to_attr="prefetched_final_report",
359+
),
360+
Prefetch(
361+
"drefoperationalupdate_set",
362+
queryset=DrefOperationalUpdate.objects.order_by("-created_at"),
363+
to_attr="prefetched_operational_updates",
364+
),
365+
)
349366
.order_by("-created_at")
350367
.filter(is_active=True)
351368
.distinct()

0 commit comments

Comments
 (0)