From b4982fde1d715417a8082cd5790fb307bbbc485b Mon Sep 17 00:00:00 2001 From: Reza <50555450+Reza98Sh@users.noreply.github.com> Date: Tue, 19 Aug 2025 00:52:04 +0330 Subject: [PATCH] Fix N+1 Query for primary_address in Company API (#10171) * Enhance CompanySerializer to use Prefetch for for better performance * Refactor CompanySerializer to improve address handling and add schema fields * implement changes suggested by joe Co-authored-by: Joe Rogers <1337joe@users.noreply.github.com> * Update src/backend/InvenTree/company/serializers.py Co-authored-by: Joe Rogers <1337joe@users.noreply.github.com> * Update src/backend/InvenTree/company/serializers.py Co-authored-by: Joe Rogers <1337joe@users.noreply.github.com> --------- Co-authored-by: Matthias Mair Co-authored-by: Joe Rogers <1337joe@users.noreply.github.com> --- src/backend/InvenTree/company/serializers.py | 28 +++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/backend/InvenTree/company/serializers.py b/src/backend/InvenTree/company/serializers.py index 3763593378..20d16a1ac0 100644 --- a/src/backend/InvenTree/company/serializers.py +++ b/src/backend/InvenTree/company/serializers.py @@ -3,8 +3,10 @@ import io from django.core.files.base import ContentFile +from django.db.models import Prefetch from django.utils.translation import gettext_lazy as _ +from drf_spectacular.utils import extend_schema_field from rest_framework import serializers from sql_util.utils import SubqueryCount from taggit.serializers import TagListSerializerField @@ -161,17 +163,37 @@ class CompanySerializer( queryset = queryset.annotate(address_count=SubqueryCount('addresses')) + queryset = queryset.prefetch_related( + Prefetch( + 'addresses', + queryset=Address.objects.filter(primary=True), + to_attr='primary_address_list', + ) + ) + return queryset - address = serializers.CharField( + address = serializers.SerializerMethodField( label=_( 'Return the string representation for the primary address. This property exists for backwards compatibility.' ), allow_null=True, - read_only=True, ) + primary_address = serializers.SerializerMethodField(allow_null=True) - primary_address = AddressSerializer(allow_null=True, read_only=True) + @extend_schema_field(serializers.CharField()) + def get_address(self, obj): + """Return string version of primary address (for backwards compatibility).""" + if hasattr(obj, 'primary_address_list') and obj.primary_address_list: + return str(obj.primary_address_list[0]) + return None + + @extend_schema_field(AddressSerializer()) + def get_primary_address(self, obj): + """Return full address object for primary address using prefetch data.""" + if hasattr(obj, 'primary_address_list') and obj.primary_address_list: + return AddressSerializer(obj.primary_address_list[0]).data + return None image = InvenTreeImageSerializerField(required=False, allow_null=True)