Angel Velásquez Angel Velásquez - 2 years ago 118
Python Question

Serializing one field from a ManyToManyField DRF

I have been lot of posts, the DRF documentation (which needs LOT of love), and I couldn't find yet how to do this without a complicated mess.

I need this output:

[{"id":1,"name":"memcheck","subscribers":["foo", "bar"]}]

If I go with the DRF way (or at least how the docs point me how to do it), then I get this output:

[{"id":1,"name":"memcheck","subscribers":["Subscriber object", "Subscriber object"]}]

I tried uncommenting and going with a second option, then I get this output:

[{"id":1,"name":"memcheck","subscribers":[{"name": "foo"}, {"name": "bar"}]}]

class Subscriber(models.Model):
name = models.CharField(max_length=100)

class Check(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(null=True, blank=True)
subscribers = models.ManyToManyField(Subscriber)

class SubscriberSerializer(serializers.ModelSerializer):
name = serializers.CharField()

class Meta:
fields = ('name', )

class CheckSerializer(serializers.ModelSerializer):
# using source=('name') or variants like: 'subscribers__name', ''
# doesnt work
subscribers = serializers.ListSerializer(child=serializers.CharField())
# subscribers = SubscriberSerializer(many=True) # --> see 2nd output

class Meta:
model = Check
fields = ('id', 'name', 'subscribers')

In other cases of ManyToMany I would like to have the list of dict, but in this case I just want a simple list with the name attr.. why is too hard to do it?

Answer Source

You just need a SlugRelatedField:

class CheckSerializer(serializers.ModelSerializer):

    subscribers = serializers.SlugRelatedField(many=True, read_only=True, slug_field='name')

    class Meta:
        model = Check
        fields = ('id', 'name', 'subscribers')
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download