0

I'm using Django Rest Framework to write my API. I want to write different values than the the id (specifically the uuid) into my serializer.

Let me give you the basic setup first. I have a model called House which has amongst other values a pk and a uuid. And I have a second model called Citizen which also has a pk and a uuid. House and Citizen have a ManyToMany relationship with each other.

I would like to have a serializer that just gives back an array of it's citizen.

Here is the not working pseudo code that I tried (and failed):

class HouseSerializer(serializers.ModelSerializer):
    address = AddressSerializer()
    citizen = serializers.UUIDField(source="citizen.uuid")

    class Meta:
        model = Table
        fields = [
            "uuid",
            "address",
            "citizen",
            ...
        ]

This serializer throws the error:

AttributeError: Got AttributeError when attempting to get a value for field `citizen` on serializer `HouseListSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `House` instance.
Original exception text was: 'ManyRelatedManager' object has no attribute 'uuid'.

But on my model for the House I have explicitly citizen = models.ManyToManyField(Citizen).

If I just don't specify any serializer and just leave citizen in the fields array, I just get an array of the PKs which I can't use.

How can I get an array of the UUIDs here?

halfer
  • 19,824
  • 17
  • 99
  • 186
J. Hesters
  • 13,117
  • 31
  • 133
  • 249

2 Answers2

2

First you'll need a serializer class for your Citizen model.

class CitizenSerializer(serializers.ModelSerializer):
    uuid = serializers.UUIDField(read_only=True)

    class Meta:
        model = Citizen
        fields = ('uuid', )

We will then add the CitizenSerializer to your HouseSerializer. Note that we need the many=True argument for ManyToManyField relation.

class HouseSerializer(serializers.ModelSerializer):
    address = AddressSerializer()
    citizen = CitizenSerializer(read_only=True, many=True)

    class Meta:
        ...

You can read more about this here

Marcell Erasmus
  • 866
  • 5
  • 15
2

You can use SlugRelatedField like this:

class HouseSerializer(serializers.ModelSerializer):
    address = AddressSerializer()
    citizen = serializers.SlugRelatedField( many=True,
    read_only=True,
    slug_field='uuid')

read the drf doc for more information.

Ehsan Nouri
  • 1,990
  • 11
  • 17
  • Thank you for your help! This seems to work, only thing is I get the error: `TypeError: Object of type 'UUID' is not JSON serializable` :( – J. Hesters Aug 22 '18 at 14:43
  • It seems like this is a deeper issue with Django... which is very unfortunate, otherwise your solution would've been a damned clear oneliner! See here https://stackoverflow.com/questions/36588126/uuid-is-not-json-serializable – J. Hesters Aug 22 '18 at 14:57