updated child validation for ListSerializer

This commit is contained in:
Pravin Kamble 2025-09-01 17:17:03 +05:30
parent 1472848501
commit c3a8ad9580
3 changed files with 104 additions and 1 deletions

View File

@ -652,6 +652,26 @@ class ListSerializer(BaseSerializer):
self.child.initial_data = data
return super().run_child_validation(data)
"""
child_instance = getattr(self.child, "instance", None)
if self.instance is not None:
pk_name = None
child_meta = getattr(self.child, "Meta", None)
model = getattr(child_meta, "model", None) if child_meta else None
if model is not None:
pk_name = model._meta.pk.name
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
break
self.child.instance = child_instance
self.child.initial_data = data
return self.child.run_validation(data)
def to_internal_value(self, data):

View File

@ -150,3 +150,21 @@ class CustomManagerModel(RESTFrameworkModel):
help_text='OneToOneTarget',
verbose_name='OneToOneTarget',
on_delete=models.CASCADE)
class ListModelForTest(RESTFrameworkModel):
name = models.CharField(max_length=100)
status = models.CharField(max_length=100, blank=True)
@property
def is_valid(self):
return self.name == 'valid'
class EmailPKModel(RESTFrameworkModel):
email = models.EmailField(primary_key=True)
name = models.CharField(max_length=100)
@property
def is_valid(self):
return self.name == 'valid'

View File

@ -5,7 +5,8 @@ from django.utils.datastructures import MultiValueDict
from rest_framework import serializers
from rest_framework.exceptions import ErrorDetail
from tests.models import (
CustomManagerModel, NullableOneToOneSource, OneToOneTarget
CustomManagerModel, EmailPKModel, ListModelForTest, NullableOneToOneSource,
OneToOneTarget
)
@ -775,3 +776,67 @@ class TestToRepresentationManagerCheck:
queryset = NullableOneToOneSource.objects.all()
serializer = self.serializer(queryset, many=True)
assert serializer.data
@pytest.mark.django_db
class TestManyTrueValidationCheck:
"""
Tests ListSerializer validation with many=True across different primary key types
(integer and email).
"""
def setup_method(self):
self.obj1 = ListModelForTest.objects.create(name="valid", status="new")
self.obj2 = ListModelForTest.objects.create(name="invalid", status="")
self.email_obj1 = EmailPKModel.objects.create(email="test@test.com", name="A")
self.email_obj2 = EmailPKModel.objects.create(email="test2@test.com", name="B")
self.serializer, self.email_serializer = self.get_serializers()
def get_serializers(self):
class ListModelForTestSerializer(serializers.ModelSerializer):
class Meta:
model = ListModelForTest
fields = ("id", "name", "status")
def validate_status(self, value):
if value and not self.instance.is_valid:
return False
return value
class EmailPKSerializer(serializers.ModelSerializer):
class Meta:
model = EmailPKModel
fields = ("email", "name")
read_only_fields = ('email',)
def validate_name(self, value):
if value and not self.instance.is_valid:
return False
return value
return ListModelForTestSerializer, EmailPKSerializer
def test_run_child_validation_with_many_true(self):
input_data = [
{"id": self.obj1.pk, "name": "other", "status": "new"},
{"id": self.obj2.pk, "name": "valid", "status": "progress"},
]
serializer = self.serializer([self.obj1, self.obj2], data=input_data, many=True)
assert serializer.is_valid(), serializer.errors
serializer = self.serializer(ListModelForTest.objects.all(), data=input_data, many=True)
assert serializer.is_valid(), serializer.errors
def test_validation_error_for_invalid_data(self):
input_data = [{"id": self.obj1.pk, "name": "", "status": "mystatus"}]
serializer = self.serializer([self.obj1], data=input_data, many=True)
assert not serializer.is_valid()
assert "name" in serializer.errors[0]
def test_email_pk_instance_validation(self):
input_data = [{"email": "test@test.com", "name": "bar"}]
serializer = self.email_serializer(instance=EmailPKModel.objects.all(), data=input_data, many=True)
assert serializer.is_valid(), serializer.errors