ThatBird ThatBird - 5 months ago 18
Python Question

Django Rest Framework nested serializer

I have models like -

class Sectors(models.Model):
sector_mc = models.TextField()

class Insector(models.Model):
foundation = models.ForeignKey(Sectors)
name = models.TextField()
value = models.FloatField(default=0)


I want my data to be in a format like-

"name": "cluster",
"children": [
{"name": "Tester", "value": 3938},
{"name": "CommunityStructure", "value": 3812},
]
},
{
"name": "graph",
"children": [
{"name": "BetweennessCentrality", "value": 34},
{"name": "LinkDistance", "value": 5731},
]
}


So "cluster" goes in "sector_mc" of "Sectors"
and cluster has children "Tester" and "CommunityStructure"(these go in "name" and "value" of "Insector" for cluster sector_mc)

Similarly "graph" goes in "sector_mc" of Sectors and graph has children "BetweennessCentrality" and "LinkDistance"(these go in "name" and "value" of "Insector" for graph sector_mc)

And so on.

How to save these with the same relation in the database and also, how to use DRF to structure it in this format. I tried using nested relationship of DRF with this but reached no where.

I need the data to be in this format for d3 sunburst chart. If there are any other workarounds, I'd be very open to know them as well. Thank you

Answer

You can create a SectorSerializer which will contain a nested serializer InsectorSerializer.

Since you are using different keys for output we can use source to get the corresponding values from the field names.

name key in the output corresponds to sector_mc, so we use sector_mc as its source.

children key in the output contains all the related instances for a particular Sectors instance. We can use FOO_set as the source for children field. Also, since there will be multiple related instances, we pass many=True parameter along with it.

class InsectorSerializer(serializers.ModelSerializer):

    class Meta:
        model = Insector
        fields = ('name', 'value')


class SectorSerializer(serializers.ModelSerializer):
    name = serializers.CharField(source='sector_mc') # get value from 'sector_mc' 
    children = InsectorSerializer(many=True, source='insector_set') # get all related instances

    class Meta:
        model = Sectors
        fields = ('name', 'children')