DRF nested serializer is not serializing data

I am trying to serialize related models for an API view.

class Dashboard(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    modified_at = models.DateTimeField(auto_now=True)
    user = models.ForeignKey(IamUser, on_delete=models.CASCADE, related_name='dashboards')
    title = models.CharField(max_length=100)
    type = models.CharField(max_length=100)
    position = models.IntegerField()
    config = models.CharField(max_length=5000, blank=True, null=True)

class WidgetLayout(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    modified_at = models.DateTimeField(auto_now=True)
    user = models.ForeignKey(IamUser, on_delete=models.CASCADE, related_name='widgets')
    dashboard = models.ForeignKey(Dashboard, on_delete=models.CASCADE, related_name='widgets')
    type = models.ForeignKey(Widget, on_delete=models.CASCADE)
    position = models.IntegerField()
    width = models.IntegerField()
    config = models.CharField(max_length=5000, blank=True, null=True)

with the following serializers

class WidgetLayoutSerializer(serializers.ModelSerializer):
    class Meta:
        model = WidgetLayout
        fields = ['id', 'type', 'position', 'width', 'config']


class DashboardSerializer(serializers.ModelSerializer):
    class Meta:
        widgets = WidgetLayoutSerializer(many=True)
        model = Dashboard
        fields = ['id', 'title', 'position', 'config', 'type', 'widgets']

The view calls the serializers like this:

        dashboards = request.user.dashboards.all()
        serializer = DashboardSerializer(dashboards, many=True)

The expected output would be a list of Widgets in their JSON serialization for each Dashboard, however, I get only a list of Widget-IDs. I discovered that, if i remove the widgets = WidgetLayoutSerializer(many=True), the result is the same, so I suspect, the serializer is not being used or referenced properly. I went through https://www.django-rest-framework.org/api-guide/relations/#example and tried to spot any difference, but could not find it.

Adding the prefetch_related for the widgets to the .all() in the view made no difference.

depth=1 is not really helpful, as I want to specify each serializer explicitly.

>Solution :

This is definitely not correct that 2 fields have the same related_name:

user = models.ForeignKey(IamUser, on_delete=models.CASCADE, related_name='widgets')
dashboard = models.ForeignKey(Dashboard, on_delete=models.CASCADE, related_name='widgets')

Remove widgets from user.

Also the field should be a base class property, not a Meta class property.

class DashboardSerializer(serializers.ModelSerializer):
    widgets = WidgetLayoutSerializer(many=True)

    class Meta:
        model = Dashboard
        fields = ['id', 'title', 'position', 'config', 'type', 'widgets']

Everything else seems good for me.

Leave a Reply