[Fixed]-Invalid data. Expected a dictionary, but got str error with serializer field in Django Rest Framework

15πŸ‘

βœ…

I’m not a big fan of this request parsing pattern. From what I understand, you want to be able to see all the contact’s details when you retrieve an AmountGiven object and at the same time be able to create and update AmountGiven by just providing the contact id.

So you can change your AmountGiven serializer to have 2 fields for the contact model field. Like this:

class AmountGivenSerializer(serializers.ModelSerializer):
    contact_detail = ContactSerializer(source='contact', read_only=True)

    class Meta:
        model = AmountGiven
        depth = 1
        fields = (
            'id', 'contact', 'contact_detail', 'amount', 'given_date', 'created'
        )

Note that the contact_detail field has a source attribute.

Now the default functionality for create and update should work out of the box (validation and everything).

And when you retrieve an AmountGiven object, you should get all the details for the contact in the contact_detail field.

Update

I missed that you need to check whether the Contact belongs to a user (however, I don’t see a user field on your Contact model, maybe you missed posting it). You can simplify that check:

class AmountGivenViewSet(viewsets.ModelViewSet):
    serializer_class = AmountGivenSerializer

    def perform_create(self, serializer):
        contact = serializer.validated_data.get('contact')
        if contact.user != self.request.user:
            raise ValidationError({'contact': ['Not a valid contact']})
        serializer.save()
πŸ‘€slider

1πŸ‘

Override the __init__() method of AmountGivenSerializer as

class AmountGivenSerializer(serializers.ModelSerializer):
    def __init__(self, *args, **kwargs):
        super(AmountGivenSerializer, self).__init__(*args, **kwargs)
        if 'view' in self.context and self.context['view'].action != 'create':
            self.fields.update({"contact": ContactSerializer()})

    class Meta:
        model = AmountGiven
        depth = 1
        fields = (
            'id', 'contact', 'amount', 'given_date', 'created'
        )

Description
The issue was the DRF expects a dict like object from contact field since you are defined a nested serializer. So, I removed the nested relationship dynamically with the help of overriding the __init__() method

πŸ‘€JPG

0πŸ‘

For those who got here but have relatively simple serializers, this error can also occur when the request data is malformed, in my case JSON encoded twice.

The serializer will decode the JSON, but as it is encoded twice request.data will still be a string. The error therefore makes sense as a "dictionnary" was expected, but we still have a "string".

You can check the output of the following to confirm whether this is the issue you are experiencing:

print(type(request.data))  # Should be <class 'dict'>
πŸ‘€FMCorz

Leave a comment