Multiple fields with the same source clobber each other · Issue #4634 · encode/django-rest-framework (original) (raw)

Hey guys, I'm getting weird behavior with many related fields. Is this an error?

Checklist

Steps to reproduce

Create a model serializer where one field renders the relation, and the other field writes to it.

class UserSerializer(serializers.ModelSerializer): dogs = DogSerializer(many=True, read_only=True) dog_ids = serializers.PrimaryKeyRelatedField(source='dogs', many=True, queryset=Dog.objects.all())

class Meta:
    fields = ('dogs', 'dog_ids',)
    model = User

Then do a patch.

PATCH /api/users/23 HTTP/1.1
Content-Type: application/json

{
    "dog_ids": [5, 9]
}

Expected behavior

It should update my model.

Actual behavior

It throws an error complaining that nested writes aren't allowed.

AssertionError at /api/users/23
The `.update()` method does not support writable nestedfields by default.
Write an explicit `.update()` method for serializer `app.serializers.DogSerializer`, or set `read_only=True` on nested serializer fields.

tl;dr

This assertion gets called, but it checks all fields rather than just the writable ones:
https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/serializers.py#L721

def raise_errors_on_nested_writes(method_name, serializer, validated_data): assert not any( isinstance(field, BaseSerializer) and (key in validated_data) and isinstance(validated_data[key], (list, dict)) for key, field in serializer.fields.items() ), ( 'The .{method_name}() method does not support writable nested' 'fields by default.\nWrite an explicit .{method_name}() method for ' 'serializer {module}.{class_name}, or set read_only=True on ' 'nested serializer fields.'.format( method_name=method_name, module=serializer.class.module, class_name=serializer.class.name ) )