'Django: How to serialize a one to many relationship

I can't seem to figure out how to serialize a one to many relationship in Django, The information doesn't seem to even appear.

My models

class DataInfo(models.Model):
    component_id = models.CharField(max_length=4)
    component_name = models.CharField(max_length=255)
    data_id = models.IntegerField()
    data_name = models.CharField(max_length=255)


class Data(models.Model):
    owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='data_owner')
    subject = models.CharField(max_length=255)
    init_date = models.DateField()
    fin_date = models.DateField()
    data_info = models.ForeignKey(DataInfo, related_name="datainfo", on_delete=models.CASCADE)

My View

class DataViewSet(viewsets.ModelViewSet):
    serializer_class = serializers.DataSerializer

    def list(self, request):
        data = models.Data.objects.using(db_to_use).select_related('data_info').all()
        return Response(self.get_serializer(data, many=True).data)

My serializers

class DataInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.DataInfo
        fields = ('id', 'component_id', 'component_name', 'data_id', 'data_name')

class DataSerializer(serializers.ModelSerializer):
    datainfo = DataInfoSerializer(source="datainfo", read_only=True)
    class Meta:
        model = models.Data
        fields = ('id', 'subject', 'init_date', 'fin_date', 'owner_id', 'data_info_id', 'datainfo')

I'm essentially just trying to do a join between Data and DataInfo, showing all the fields of Data and DataInfo in one view (not nested). I tried doing a select_related, putting a source attribute, nothing seems to work. The response I get is just all fields of the Data table with no fields of the DataInfo table. Am I missing something with the serialization?



Solution 1:[1]

Have you tried adding many=True to where you add that DataInfoSerializer?

That is,

class DataSerializer(serializers.ModelSerializer):
    datainfo = DataInfoSerializer(source="datainfo", read_only=True, many=True)
    # ...

(As an aside, Data, DataInfo, data_info and datainfo are rather terrible names. In particular, related_names should be somehow plural or implying plurality, unless they're on OneToOneFields.)

Solution 2:[2]

This should work:

class DataSerializer(serializers.ModelSerializer):
    datainfo = DataInfoSerializer()

    class Meta:
        model = Data
        fields = '__all__'

Also, try explicitly mentioning the data_info = models.ForeignKey(DataInfo, to_field=<data-info-id>) in Data model.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 AKX
Solution 2 addu390