Return nested serializer in serializer method field

20,041

Solution 1

Try this;

followers = BaseUserSmallSerializer(source='get_followers', many=True)

OR

You can use serializer inside methodfield;

def get_followers(self, obj):
   followers_queryset = #get queryset of followers
   return  BaseUserSmallSerializer(followers_queryset, many=True).data

Solution 2

If you prefer a more generic solution:

SerializerMethodNestedSerializer which works same as serializers.SerializerMethodField but wraps the result with the passed serializer and returns a dict

class SerializerMethodNestedSerializer(serializers.SerializerMethodField):
    """Returns nested serializer in serializer method field"""

    def __init__(self, kls, kls_kwargs=None, **kwargs):
        self.kls = kls
        self.kls_kwargs = kls_kwargs or {}
        super(SerializerMethodNestedSerializer, self).__init__(**kwargs)

    def to_representation(self, value):
        repr_value = super(SerializerMethodNestedSerializer, self).to_representation(value)
        if repr_value is not None:
            return self.kls(repr_value, **self.kls_kwargs).data

Usage

class SomeSerializer(serializers.ModelSerializer):
    payment_method = SerializerMethodNestedSerializer(kls=PaymentCardSerializer)

    def get_payment_method(self, obj):
        return PaymentCard.objects.filter(user=obj.user, active=True).first()

    class Meta:
        model = Profile
        fields = ("payment_method",)
class PaymentCardSerializer(serializers.ModelSerializer):

    class Meta:
        fields = ('date_created', 'provider', 'external_id',)
        model = PaymentCard

The expected output of SerializerMethodNestedSerializer(kls=PaymentCardSerializer)

None or {'date_created': '2020-08-31', 'provider': 4, 'external_id': '123'}
Share:
20,041

Related videos on Youtube

Ambroise Collon
Author by

Ambroise Collon

Freelance iOS developper

Updated on September 01, 2020

Comments

  • Ambroise Collon
    Ambroise Collon over 3 years

    I have a method field called followers. I get the list of followers in a SerializerMethodField :

    followers = serializers.SerializerMethodField()
    

    I want to format the result with a specific serializer called BaseUserSmallSerializer. How should I implement the method get_followers to achieve that ?

  • Ambroise Collon
    Ambroise Collon over 8 years
    It doesn't work because followers is not a property of my class BaseUser. I get : Original exception text was: 'BaseUser' object has no attribute 'get_following'.
  • Geo Jacob
    Geo Jacob over 8 years
    ok, either you can write a model method or you can use BaseUserSmallSerializer inside serializerMethod field.
  • Ambroise Collon
    Ambroise Collon over 8 years
    OK i got it. Thanks for the quick and complete answer. For the record, solution 2 is what I was looking for.
  • Ege Aydın
    Ege Aydın almost 7 years
    If you ever get your serializer is not json serializable error, you probably did not did call data property on the serializer. BaseUserSmallSerializer(followers_queryset, many=True).data
  • Aniket Malik
    Aniket Malik over 4 years
    @Geo Jacob God bless you. Thanks