Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to nest two serializers with same model

I have two serializers with same model. I want to nest them.

Unfortunately this approach does not work:

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['name', 'word_count']


class BetterBookSerializer(serializers.ModelSerializer):
    book = BookSerializer(many=False)

    class Meta:
        model = Book
        fields = ('id', 'book')

Expected result:

{
  "id": 123,
  "book": {
    "name": "book_name",
    "word_count": 123
  }
}
like image 615
Nuts Avatar asked Dec 13 '22 15:12

Nuts


2 Answers

Use source=* instead of many=True as

class BetterBookSerializer(serializers.ModelSerializer):
    book = BookSerializer(source='*')

    class Meta:
        model = Book
        fields = ('id', 'book')

From the doc,

The value source='*' has a special meaning, and is used to indicate that the entire object should be passed through to the field. This can be useful for creating nested representations, or for fields which require access to the complete object in order to determine the output representation.

like image 77
JPG Avatar answered Dec 30 '22 15:12

JPG


You can achieve the desired output like this:

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['name', 'word_count']

class BetterBookSerializer(serializers.ModelSerializer):
    book = serializers.SerializerMethodField(read_only=True)

    class Meta:
         model = Book
         fields = ('id', 'book')

    def get_book(self, obj):
         return BookSerializer(obj).data

Small Update: Although my approach to solve your problem works just fine, the answer from @JPG mentioning source='*' option is a good way to go. In that way you can easily use the nested serializer when creating new object.

like image 39
Enthusiast Martin Avatar answered Dec 30 '22 15:12

Enthusiast Martin