18

I'm currently working on Django with Django Rest Framwork.

I can't update my object within nested object field.


serializer.py

class OwnerSerializer(serializers.ModelSerializer):
    class Meta:
        model =  Owner
        fields = ('id', 'name')

class CarSerializer(serializers.ModelSerializer):
    owner = ownerSerializer(many=False, read_only=False) 
    class Meta:
        model =  Car
        fields = ('id', 'name', 'owner')

view.py

class OwnerViewSet(viewsets.ModelViewSet):
    queryset = Owner.objects.all()
    serializer_class = OwnerSerializer

class CarViewSet(viewsets.ModelViewSet):
    serializer_class = CarSerializer
    queryset = Car.objects.all()

    def create(self, request):
        serialized = self.serializer_class(data=request.DATA)
        if serialized.is_valid():
            serialized.save()
            return Response(status=HTTP_202_ACCEPTED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

When I do this :

Request URL:http://localhost:9000/api/v1/cars/1/?format=json
Request Method:PUT
Request Paylod :
{
    "id":1,
    "name": "TEST", 
    "ower": {
        "id":1,
        "name": "owner_test"
    }
}

I get the following Response :

The `.update()` method does not support writable nestedfields by default.
Write an explicit `.update()` method for serializer `app.serializers.CarSerializer`,
or set `read_only=True` on nested serializer fields.

Knowing :

  • I want to keep the owner serialization on GET;
  • We can imagine the car nested by another object and ect...

How can I do if i want to change the owner when I update the car.

CheapD AKA Ju
  • 713
  • 2
  • 7
  • 21
  • 3
    possible duplicate of [django-rest-framework 3.0 create or update in nested serializer](http://stackoverflow.com/questions/27434593/django-rest-framework-3-0-create-or-update-in-nested-serializer) – Kevin Brown-Silva Jan 07 '15 at 17:41
  • Tanks ! I repeat myself sorry, but why the override is in the serializer and not in the view, like : [Django-doc](http://www.django-rest-framework.org/api-guide/viewsets/#marking-extra-actions-for-routing), that way can return status ?? – CheapD AKA Ju Jan 08 '15 at 07:51
  • if you want to change by id the anser is override to_representation method https://stackoverflow.com/questions/41394761/the-create-method-does-not-support-writable-nested-fields-by-default?noredirect=1&lq=1 – Alex78191 Oct 23 '19 at 01:24
  • I get this error in post method and put. – reza_khalafi Sep 25 '21 at 13:10

2 Answers2

8

A little late, but, Try this,

class OwnerSerializer(serializers.ModelSerializer):
    class Meta:
        model =  Owner
        fields = ('id', 'name')
        extra_kwargs = {
            'id': {
                'read_only': False, 
                'required': True
             }
        } #very important

    def create(self, validated_data):
        # As before.
        ...

    def update(self, instance, validated_data):
        # Update the  instance
        instance.some_field = validated_data['some_field']
        instance.save()

        # Delete any detail not included in the request
        owner_ids = [item['owner_id'] for item in validated_data['owners']]
        for owner in cars.owners.all():
            if owner.id not in owner_ids:
                owner.delete()

        # Create or update owner 
        for owner in validated_data['owners']:
            ownerObj = Owner.objects.get(pk=item['id'])
            if ownerObje:
                ownerObj.some_field=item['some_field']
                ....fields...
            else:
               ownerObj = Owner.create(car=instance,**owner)
            ownerObj.save()

        return instance
scriptmonster
  • 2,741
  • 21
  • 29
Erick lxvi
  • 127
  • 1
  • 4
2

Just in-case someone stumbles on this

had the same error in my case but setting read_only to True fixed it for me.

    owner = ownerSerializer(many=False, read_only=True) 

Note that, this field won't appear in the form when posting data to the api.

pycod333
  • 764
  • 2
  • 7
  • 16
  • 2
    The question is `how to change the owner when I update the car?`. – Alex78191 Oct 23 '19 at 00:35
  • @Alex78191 Exactly where I'm stuck at the moment! I need this field as part of a PATCH request so I, of course, should be able to change it but in my use case I also need to be able to make it null on the backend. Thanks, DRF? – ankush981 Aug 25 '21 at 12:27