1

I have serializers in the following format:

CounterPartyCompanySerializer:

class CounterPartyCompanySerializer(serializers.ModelSerializer):
class Meta:
    model = ClientCompany
    fields = (
        "id",
        "company_name",
        "address_line1",
    )
    extra_kwargs = {
        "id": {
            "read_only": False,
            "required": False,
        },
    }

CounterPartySerializer:

class CounterPartySerializer(serializers.ModelSerializer):
company = CounterPartyCompanySerializer()

class Meta:
    model = Client
    fields = (
        "id",
        "company",
        "client_name",
    )
    extra_kwargs = {
        "id": {
            "read_only": False,
            "required": False,
        },
    }

and GiftAndEntertainmentSerializer:

class GiftAndEntertainmentSerializer(serializers.ModelSerializer):
counter_party = CounterPartySerializer()

class Meta:
    model = GiftAndEntertainment
    fields = (
        "id",
        "counter_party",
        "value",

    )

Case-I :: It works when I do the following:

result_list = GiftAndEntertainment.objects.all()

    serializer = GiftAndEntertainmentSerializer(
        result_list, many=True, context={"request": request}
    )

But, it doesn't work when I pass the custom queryset like:

result_list = GiftAndEntertainment.objects.values(
        "counter_party",
        "value"
    ).annotate(
        total=ExpressionWrapper(Sum("value"), output_field=DecimalField())
    )

    serializer = GiftAndEntertainmentSerializer(
        result_list, many=True, context={"request": request}
    )

Here, "counter_party" is ForeignKey mapped entity and the queryset passes the primary-key id of counter_party entity. I thought the serializer will convert the pk to its corresponding entities like its doing in the case-I but that is not happening automatically. Any help here would save my life. I have spent an entire day trying to achieve this but failed every-single time.

ishwor kafley
  • 938
  • 14
  • 32

1 Answers1

0

with the help of this SO thread, I was able to achieve this.. What i did was :

First, I prepare GiftAndEntertainment subquery with group by "counter_party" where I sum all value fields and mark primary key id as pk for outer query.

from django.db.models import ExpressionWrapper, DecimalField, Subquery, Sum, OuterRef

    group_by = (
        GiftAndEntertainment.objects.values(
            "counter_party"
        )
        .annotate(
            total=ExpressionWrapper(
                Sum("value"), output_field=DecimalField()
            )
        )
        .filter(id=OuterRef("pk"))
    )

Then I select all rows from GiftAndEntertainment plus subquery result as row_value field.

    group_by_with_total = GiftAndEntertainment.objects.annotate(
        row_value=Subquery(group_by.values("total"))
    )

    serializer = GiftAndEntertainmentSerializer(
        group_by_with_total, many=True, context={"request": request}
    )

with this, the serializer happily accepted the queryset and even mapped the corresponding entities automatically.

ishwor kafley
  • 938
  • 14
  • 32