Reputation: 6432
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
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