0

I want to customise the output of serializer to group some fields of the models into a nested dictionary, so I override to_representation:

My models.py

class Snippet(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    title = models.CharField(max_length=100, blank=True, default='')
    code = models.TextField()
    linenos = models.BooleanField(default=False)
    language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
    style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)
    owner = models.ForeignKey('auth.User', related_name='snippets', on_delete=models.CASCADE)

    class Meta:
        ordering = ['created']

My serializers.py

class SnippetSerializer(serializers.ModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.username')
    
    class Meta:
        model = Snippet
        fields = ['id', 'title', 'code', 'linenos', 'language', 'style', 'owner']

    def to_representation(self, instance):
        return {
            'id': instance.id,
            'owner': instance.owner.username,
            'therest': {
                'title': instance.title,
                'code': instance.code,
                'linenos': instance.linenos,
                'language': instance.language,
                'style': instance.style
            }
        }

class UserSerializer(serializers.ModelSerializer):
    snippets = SnippetSerializer

    class Meta:
        model = User
        fields = ['id', 'username', 'snippets']
        depth = 1

My expected outcome of users serializer is:

[
    {
        "id": 1,
        "username": "admin",
        "snippets": [
            {
                "id": 1,
                "owner": "admin",
                "therest": {
                    "title": "",
                    "code": "foo=\"bar\"\\n",
                    "linenos": false,
                    "language": "python",
                    "style": "abap"
                }
            }
        ]
    }
]

but I got this instead:

[
    {
        "id": 1,
        "username": "admin",
        "snippets": [
            {
                "id": 1,
                "created": "2022-09-01T17:11:59.743112Z",
                "title": "",
                "code": "foo=\"bar\"\\n",
                "linenos": false,
                "language": "python",
                "style": "abap",
                "owner": 1
            },
        ]
    }
]

Nested snippets in UserSerializer does not inherit to_representation from SnippetSerializer. Did I miss something?

cdev
  • 31
  • 3
  • maybe ```snippets = SnippetSerializer(many=True)``` helps, you should pass an object, not the class – Amrez Sep 01 '22 at 23:52
  • Wow this work, thank you. I'm not reading the doc carefully. Could you please explain why "many=True" make this difference? – cdev Sep 02 '22 at 11:10
  • by setting ```many=True``` you tell drf that queryset contains mutiple items (a list of items) so drf needs to serialize each item with serializer class (and ```serializer.data``` will be a list) if you don't set this argument it means queryset is a single instance and ```serializer.data``` will be a single object) https://stackoverflow.com/a/51229456/16004568 – Amrez Sep 02 '22 at 11:31
  • documentation https://www.django-rest-framework.org/api-guide/relations/#nested-relationships – Amrez Sep 02 '22 at 11:31
  • Without `many=true` it still return a list of snippets, but it does not inherit `to_representation` from `SnippetSerializer`. That is the reason why I missed this flag. https://prnt.sc/ydcihb7Fc56X – cdev Sep 02 '22 at 15:54

0 Answers0