user659154 user659154 - 2 months ago 9
JSON Question

customize Django Rest Framework serializers output?

I have a Django model like this:

class Sections(models.Model):
section_id = models.CharField(max_length=127, null=True, blank=True)
title = models.CharField(max_length=255)
description = models.TextField(null=True, blank=True)

class Risk(models.Model):
title = models.CharField(max_length=256, null=False, blank=False)
section = models.ForeignKey(Sections, related_name='risks')

class Actions(models.Model):
title = models.CharField(max_length=256, null=False, blank=False)
section = models.ForeignKey(Sections, related_name='actions')


And serializers like that :

class RiskSerializer(serializers.ModelSerializer):
class Meta:
model = Risk
fields = ('id', 'title',)

class ActionsSerializer(serializers.ModelSerializer):
class Meta:
model = Actions
fields = ('id', 'title',)

class RiskActionPerSectionsSerializer(serializers.ModelSerializer):
risks = RiskSerializer(many=True, read_only=True)
actions = ActionsSerializer(many=True, read_only=True)

class Meta:
model = Sections
fields = ('section_id', 'risks', 'actions')
depth = 1


When accessing the RiskActionPerSectionSerializer over a view, I get the following output:

[
{
"actions": [
{
"id": 2,
"title": "Actions 2"
},
{
"id": 1,
"title": "Actions 1"
}
],
"risks": [
{
"id": 2,
"title": "Risk 2"
},
{
"id": 1,
"title": "Risk 1"
}
],
"section_id": "section 1"
}
.....
]


It s fine but I would prefer to have that :

{
"section 1": {
"risks": [
{
"id": 2,
"title": "Risk 2"
},
{
"id": 1,
"title": "Risk 1"
}
],
"actions": [
{
"id": 2,
"title": "Actions 2"
},
{
"id": 1,
"title": "Actions 1"
}
]
}
}


How can I do that with Django Rest Framework ?

Answer

You could override to_representation() method of your serializer:

class RiskActionPerSectionsSerializer(serializers.ModelSerializer):

   class Meta:
       model = Sections
       fields = ('section_id', 'risks', 'actions')
       depth = 1

   def to_representation(self, instance):
       response_dict = dict()
       response_dict[instance.section_id] = {
           'actions': ActionsSerializer(instance.actions.all(), many=True).data,
           'risks': RiskSerializer(instance.risks.all(), many=True).data
       }
       return response_dict