angrysumit
angrysumit

Reputation: 221

Specifying field names in serializer class acting as another serializer class's field

Suppose for below ModelSerializer class

class UserSongSerializer(serializers.ModelSerializer):
    user            = serializers.SerializerMethodField()
    song_likes      = serializers.ReadOnlyField() # This is model's property field
    song_shares     = serializers.ReadOnlyField()
    song_plays      = serializers.ReadOnlyField()
    song_price      = serializers.ReadOnlyField()   
    genre           = GenreSerializer(many=True,required=False,context={'key':5})
    language        = LanguageSerializer(many=True, required=False)

Passing specific context kwarg like below

genre           = GenreSerializer(many=True,required=False,context={'fields':['name']})

Since I want to retrieve only name field in Genre model class in some specific cases, I overrided GenreSerializer class's get_fields_name method so that I can mention specific fields only when required via context

class GenreSerializer(serializers.ModelSerializer):

    def get_field_names(self, *args, **kwargs):
        """
        Overriding ModelSerializer get_field_names method for getting only specific fields in serializer when mentioned in SerializerClass arguments
        """

        field_names = self.context.get('fields', None)
        if field_names:
            return field_names

        return super(GenreSerializer, self).get_field_names(*args, **kwargs)        

    class Meta:
        model = Genre
        fields = '__all__'

However, I am unable to get any 'fields' (getting None) key inside overrided get_fields_name method. I know of other ways as well like using StringRelatedField but that would change the output representation to

"genre":[
        "Pop",
        "Rock"
        ]

Whereas, I want to stick to my original representation

"genre": [
                {
                    "id": 3,
                    "name": "Pop",
                    "created_date": "2018-09-05T17:05:59.705422+05:30",
                    "updated_date": "2018-09-20T14:43:02.062107+05:30",
                    "status": false
                },
                {
                    "id": 4,
                    "name": "Rock",
                    "created_date": "2018-09-05T17:06:06.889047+05:30",
                    "updated_date": "2018-09-17T16:45:22.684044+05:30",
                    "status": true
                },
                {
                    "id": 5,
                    "name": "Classical",
                    "created_date": "2018-09-05T17:06:14.216260+05:30",
                    "updated_date": "2018-09-05T17:06:14.275082+05:30",
                    "status": true
                }
            ]

UPDATE - What I want is like this

"genre": [
                {

                    "name": "Pop"

                },
                {

                    "name": "Rock"

                },
                {

                    "name": "Classical"

                }
            ]

Upvotes: 0

Views: 224

Answers (1)

Linovia
Linovia

Reputation: 20996

Contexts are meant to be set to the root serializer only.

Whenever UserSongSerializer will be instantiated it'll override the nested genre context.

If you are using generic views, you'll want to override the view's get_serializer_context and add your own context there. It's documented at the bottom of the methods section

PS: context are "shared" to serializers, fields, validators.

PPS: Don't alter context after it's been set you it's going to be sort of undefined behavior.

Upvotes: 2

Related Questions