diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index a3d68b03..80ae9a9d 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -680,10 +680,29 @@ class ListSerializer(BaseSerializer): api_settings.NON_FIELD_ERRORS_KEY: [message] }, code='min_length') + # Validate that instance length matches data length when instance is provided + if self.instance is not None and not isinstance(self.instance, models.manager.BaseManager): + if len(self.instance) != len(data): + raise AssertionError( + 'Mismatched instances and data items (%s instances for %s data items)' % + (len(self.instance), len(data)) + ) + ret = [] errors = [] - for item in data: + for idx, item in enumerate(data): + # Set the instance on the child serializer to the corresponding item + # when validating in the context of many=True + if self.instance is not None and isinstance(self.instance, (list, tuple)): + child_instance = self.instance[idx] + else: + child_instance = getattr(self, 'instance', None) + + # Temporarily bind the child instance + old_child_instance = self.child.instance + self.child.instance = child_instance + try: validated = self.child.run_validation(item) except ValidationError as exc: @@ -691,6 +710,9 @@ class ListSerializer(BaseSerializer): else: ret.append(validated) errors.append({}) + finally: + # Restore the original instance + self.child.instance = old_child_instance if any(errors): raise ValidationError(errors) diff --git a/tests/test_serializer.py b/tests/test_serializer.py index 39d9238e..07d34b89 100644 --- a/tests/test_serializer.py +++ b/tests/test_serializer.py @@ -836,11 +836,13 @@ class TestMultipleObjectsValidation(unittest.TestCase): def test_exception_raised_when_data_and_instance_length_different(self): + serializer = MyClassSerializer( + data=[{'value': 'set', 'id': instance.id} for instance in + self.objs], + instance=self.objs[:-1], + many=True, + partial=True, + ) + with self.assertRaises(AssertionError): - MyClassSerializer( - data=[{'value': 'set', 'id': instance.id} for instance in - self.objs], - instance=self.objs[:-1], - many=True, - partial=True, - ) + serializer.is_valid()