From ea9e2e581f14a9a81cc1eac0affba637e89c2540 Mon Sep 17 00:00:00 2001 From: Kara Engelhardt Date: Fri, 15 Nov 2024 16:25:53 +0100 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20Prefetch=20attachment?= =?UTF-8?q?=20infos=20in=20optimize=5Fmessage=5Fqueryset?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- froide/foirequest/api_views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/froide/foirequest/api_views.py b/froide/foirequest/api_views.py index 4c67dff63..7f495852a 100644 --- a/froide/foirequest/api_views.py +++ b/froide/foirequest/api_views.py @@ -351,7 +351,7 @@ def optimize_query(self, qs): def optimize_message_queryset(request, qs): atts = get_read_foiattachment_queryset( request, queryset=FoiAttachment.objects.filter(belongs_to__in=qs) - ) + ).prefetch_related("belongs_to", "document", "converted", "redacted") return qs.prefetch_related( "request", "request__user", From 4db9a4f6cbb09ee0c3ed8d9cc50012825874ad1d Mon Sep 17 00:00:00 2001 From: Kara Engelhardt Date: Fri, 15 Nov 2024 16:26:53 +0100 Subject: [PATCH 2/2] =?UTF-8?q?=E2=9C=85=20Add=20test=20for=20FoiMessageSe?= =?UTF-8?q?rializer=20performance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- froide/foirequest/tests/test_api.py | 63 ++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/froide/foirequest/tests/test_api.py b/froide/foirequest/tests/test_api.py index 94b5d16a9..111628d6f 100644 --- a/froide/foirequest/tests/test_api.py +++ b/froide/foirequest/tests/test_api.py @@ -4,14 +4,18 @@ from django.conf import settings from django.contrib.auth import get_user_model +from django.contrib.auth.models import AnonymousUser from django.core import mail -from django.test import TestCase +from django.db import connection +from django.test import RequestFactory, TestCase +from django.test.utils import CaptureQueriesContext from django.urls import reverse from django.utils import timezone import pytest from oauth2_provider.models import get_access_token_model, get_application_model +from froide.foirequest.api_views import FoiMessageSerializer from froide.foirequest.models import FoiAttachment, FoiRequest from froide.foirequest.tests import factories from froide.publicbody.models import PublicBody @@ -391,3 +395,60 @@ def test_redacted_description(world, client): assert fr.description not in str(response.json()) assert fr.description_redacted in str(response.json()) assert fr.description_redacted in str(response.json()) + + +@pytest.fixture +def many_attachment_foimessage(foi_message): + for i in range(100): + red_att = FoiAttachment( + belongs_to=foi_message, + name=f"{i}_redacted.pdf", + is_redacted=True, + filetype="application/pdf", + approved=True, + can_approve=True, + ) + red_att.approve_and_save() + orig_att = FoiAttachment( + belongs_to=foi_message, + name=f"{i}.pdf", + is_redacted=False, + filetype="application/pdf", + approved=False, + can_approve=False, + redacted=red_att, + ) + orig_att.approve_and_save() + return foi_message + + +def selective_equal_dicts(a, b, ignore_keys): + ka = set(a).difference(ignore_keys) + kb = set(b).difference(ignore_keys) + return ka == kb and all(a[k] == b[k] for k in ka) + + +@pytest.mark.django_db +def test_foi_message_serializer_performance(world, client, many_attachment_foimessage): + request = RequestFactory().get("/") + request.user = AnonymousUser() + + with CaptureQueriesContext(connection) as ctx: + serializer = FoiMessageSerializer( + many_attachment_foimessage, context={"request": request} + ) + data = serializer.data + assert len(ctx.captured_queries) < 10 + + with CaptureQueriesContext(connection) as ctx: + api_data = client.get( + reverse("api:message-detail", kwargs={"pk": many_attachment_foimessage.pk}) + ) + assert len(ctx.captured_queries) < 10 + assert api_data.json().keys() == data.keys() + assert len(api_data.json()["attachments"]) == len(data["attachments"]) + for ( + a, + b, + ) in zip(api_data.json()["attachments"], data["attachments"], strict=True): + assert selective_equal_dicts(a, b, {"file_url"})