pd farhad
pd farhad

Reputation: 6432

How to return object details and Aggregated data under the same Django Rest API

I want to return Object details and Aggregated data under the same Django rest api. Can it be possible from ModelViewSet? If not what is the correct way of doing this?

Here is my Code.

#Tin 
class TinTable(CoreModel):
    tin=models.CharField(unique=True, max_length=30)
    assessee_name=models.CharField(max_length=500)

def __str__(self):
    return self.tin

# Financial Year
class FinancialYear(CoreModel):
    financial_year = models.CharField(max_length = 50)

    class Meta:
        ordering = ["start_year"]
    def __str__(self):
        return self.financial_year

Ledger Class

# Ledger 
class Ledger(CoreModel):
    
    UNDISPUTED = 0
    APPEAL = 1
    TRIB = 2
    HC = 3
    ONE_SEVENTY_THREE = 4
    ONE_TWEENTY_ONE = 5
    ADR = 6
    

    Ledger_SECTION_CHOICES = (
        (UNDISPUTED, 'Undisputed'),
        (APPEAL, 'Appeal'),
        (TRIB, 'Tribunal'),
        (HC, 'High Court'),
        (ONE_SEVENTY_THREE, '173'),
        (ONE_TWEENTY_ONE, '121/A'),
        (ADR, 'ADR')

    )
    tin=models.ForeignKey(TinTable, on_delete = models.CASCADE)
    financial_year = models.ForeignKey(FinancialYear, on_delete = models.CASCADE)


    demand = models.FloatField(default = 0.0 ) #demand
    disputed_demand = models.FloatField(default=0.0)

    payment = models.FloatField(default = 0.0 ) #payment
    balance = models.FloatField(default = 0.0 )
    status = models.PositiveSmallIntegerField(
        choices=Ledger_SECTION_CHOICES, default=UNDISPUTED)

    comment = models.CharField(max_length=500, blank=True)

    def __str__(self):
        return self.tin.tin

Serializer of Ledger

class LedgerSerializer(serializers.ModelSerializer):
    financial_year = serializers.PrimaryKeyRelatedField(
        queryset=FinancialYear.objects.all(), source='financial_year', write_only=True
    )
    tin = serializers.PrimaryKeyRelatedField(
        queryset=TinTable.objects.all(), source='tin', write_only=True
    )
    assessee_name = serializers.ReadOnlyField(
        source='tin.assessee_name'
    )
    
    class Meta:
        model = Ledger
        fields = ('tin','assessee_name','financial_year','demand','disputed_demand', 'payment','status')

View of Ledger

class LedgerView(viewsets.ModelViewSet):
    serializer_class = LedgerSerializer
    queryset = Ledger.objects.active()

The output I want

{
    "results":[
        {
            "tin":"222222222222",
            "name":"Karim",
            "total_disputed": 5000,
            "total_undisputed": 900,
            "total_payment": 500,

            "financial_details":[
                {
                    "year": "2017-2018",
                    "undisputed":900,
                    "disputed":0,
                    "payment":500,
                    "status":"undisputed"
                },
                {
                    "year": "2018-2019",
                    "undisputed":0,
                    "disputed":5000,
                    "payment":0,
                    "status":"disputed"
                }

            ]
            

        },
        {
            "tin":"3333333333333",
            "name":"Rahim",
            "total_disputed": 8000,
            "total_undisputed": 1900,
            "total_payment": 1500,

            "financial_details":[
                {
                    "year": "2017-2018",
                    "undisputed":900,
                    "disputed":3000,
                    "payment":500,
                    "status":"undisputed"
                },
                {
                    "year": "2018-2019",
                    "undisputed":1000,
                    "disputed":5000,
                    "payment":1000,
                    "status":"disputed"
                },

               ........ # more data
            ]
            

        },
              ........ # more data
    ]
}

It would be so helpful to get a detailed answer for it. Thanks in advance.

Upvotes: 0

Views: 191

Answers (1)

Mahmoud Adel
Mahmoud Adel

Reputation: 1330

You need to write a serializer to serialize financial_details, for ex:

class FinancialYearSerializer(serializers.ModelSerializer):
       class Meta:
            model = FinancialYear
            fields = # your desired fields...

class LedgerSerializer(serializers.ModelSerializer):
    financial_details = FinancialYearSerializer(source='financial_year', read_only=True, many=True)
    # the rest of your fields
    
    class Meta:
        model = Ledger
        fields = ('tin','assessee_name','financial_year','demand','disputed_demand', 'payment','status')

For other fields which will hold aggregated data, you can use SerializerMethodField() as the docs describe.

TIP:

You should add related_name to your ForeignKey() fields for reverse relations, Django is already creating it with default naming but it's better to set yours.

tin = models.ForeignKey(TinTable, on_delete = models.CASCADE, related_name='ledgers')
financial_year = models.ForeignKey(FinancialYear, on_delete = models.CASCADE, related_name='ledgers')

Upvotes: 1

Related Questions