Nico Bleiler
Nico Bleiler

Reputation: 493

How to change Representation of Many to Many related object in Django Rest Framework

I want the complete related model on GET and use the id's on CREATE, UPDATE and DELETE. I try to use to_representation. So i want to create an array of dicts called users which should show the complete users.

But i get the error "unhashable type: 'ReturnDict'" when i add the dict in the object, it works fine if i would do it for a single user by writing to the array directly.

class CompanySerializer(serializers.ModelSerializer):
    #users = UserSerializer(many=True)
    created_at = serializers.DateTimeField()
    updated_at = serializers.DateTimeField()
    class Meta:
        model = Company
        fields = ['id', 'name', 'street', 'city', 'postal_code', 'state', 'company_form', 'users', 'created_at', 'updated_at']        

    def to_representation(self, instance):
        representation = super(CompanySerializer, self).to_representation(instance)
        representation['company_form'] = CompanyFormSerializer(instance.company_form).data
        representation['users'] = []
        for entry in instance.users.all():
            user = {UserSerializer(entry).data}
            representation['users'].extend(user)
        return representation

Upvotes: 2

Views: 1584

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477200

There is no need to do this manually, you can add serializers to your serializer, like:

class CompanySerializer(serializers.ModelSerializer):
    users = UserSerializer(read_only=True, many=True)
    company_form = CompanyFormSerializer()
    created_at = serializers.DateTimeField()
    updated_at = serializers.DateTimeField()

    class Meta:
        model = Company
        fields = ['id', 'name', 'street', 'city', 'postal_code', 'state', 'company_form', 'users', 'created_at', 'updated_at']

For more information, see the Dealing with nested objects section of the Django REST Framework documentation.

Your to_representation model was wrong on two parts:

  1. you wrapped the result of the .data in a set, but as you found out, a dictionary can not be placed in a dictionary, since a set is mutable; and
  2. you should use .append(..) instead of .extend(..) here.
def to_representation(self, instance):
    representation = super(CompanySerializer, self).to_representation(instance)
    representation['company_form'] = CompanyFormSerializer(instance.company_form).data
    representation['users'] = []
    for entry in instance.users.all():
        user = UserSerializer(entry).data
        representation['users'].append(user)
    return representation

But that being said, it is in my opinion, bad software design to aim to do this yourself. Django has a lot of tooling to handle relationships properly through URIs, etc.

Upvotes: 4

Related Questions