diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index a13645075..faff64c5b 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -662,14 +662,40 @@ class ListSerializer(BaseSerializer): if model is not None: pk_name = model._meta.pk.name + obj_id = None if pk_name: - obj_id = data.get(pk_name, data.get("pk", data.get("id"))) - if obj_id is not None: - for obj in self.instance: - if hasattr(obj, pk_name) and getattr(obj, pk_name) == obj_id: - child_instance = obj + for field_name, field in self.child.fields.items(): + if getattr(field, "source", None) == pk_name: + obj_id = data.get(field_name) + if obj_id is not None: break + if obj_id is None: + obj_id = data.get(pk_name) or data.get("pk") or data.get("id") + + resolved_instance = None + + if obj_id is not None and pk_name: + try: + obj_id = model._meta.pk.to_python(obj_id) + except Exception: + pass + + if not hasattr(self, "_instance_index"): + self._instance_index = { + getattr(obj, pk_name): obj for obj in self.instance + } + + resolved_instance = self._instance_index.get(obj_id) + + if resolved_instance is None: + if model is not None and self.context.get("allow_create", True): + resolved_instance = model() + else: + resolved_instance = child_instance + + child_instance = resolved_instance + self.child.instance = child_instance self.child.initial_data = data return self.child.run_validation(data) diff --git a/tests/test_serializer_lists.py b/tests/test_serializer_lists.py index 6155a9ca7..041cbb2ed 100644 --- a/tests/test_serializer_lists.py +++ b/tests/test_serializer_lists.py @@ -860,7 +860,7 @@ class TestManyTrueValidationCheck: input_data = [ { - "uuid": "t3308237e-18d8-4074-9d05-79cc0fdb5bb3", + "uuid": "c20f2f31-65a3-451f-ae7d-e939b7d9f84b", "name": "bar", }, ]