@@ -153,6 +153,61 @@ def test_validate_html_input(self):
153153 assert serializer .is_valid ()
154154 assert serializer .validated_data == expected_output
155155
156+ def test_update_allow_custom_child_validation (self ):
157+ """
158+ Update a list of objects thanks custom run_child_validation implementation.
159+ """
160+
161+ class TestUpdateSerializer (serializers .Serializer ):
162+ integer = serializers .IntegerField ()
163+ boolean = serializers .BooleanField ()
164+
165+ def update (self , instance , validated_data ):
166+ instance ._data .update (validated_data )
167+ return instance
168+
169+ def validate (self , data ):
170+ # self.instance is set to current BasicObject instance
171+ assert isinstance (self .instance , BasicObject )
172+ # self.initial_data is current dictionary
173+ assert isinstance (self .initial_data , dict )
174+ assert self .initial_data ["pk" ] == self .instance .pk
175+ return super ().validate (data )
176+
177+ class ListUpdateSerializer (serializers .ListSerializer ):
178+ child = TestUpdateSerializer ()
179+
180+ def run_child_validation (self , data ):
181+ # find related instance in self.instance list
182+ child_instance = next (o for o in self .instance if o .pk == data ["pk" ])
183+ # set instance and initial_data for child serializer
184+ self .child .instance = child_instance
185+ self .child .initial_data = data
186+ return super ().run_child_validation (data )
187+
188+ def update (self , instance , validated_data ):
189+ return [
190+ self .child .update (instance , attrs )
191+ for instance , attrs in zip (self .instance , validated_data )
192+ ]
193+
194+ instance = [
195+ BasicObject (pk = 1 , integer = 11 , private_field = "a" ),
196+ BasicObject (pk = 2 , integer = 22 , private_field = "b" ),
197+ ]
198+ input_data = [
199+ {"pk" : 1 , "integer" : "123" , "boolean" : "true" },
200+ {"pk" : 2 , "integer" : "456" , "boolean" : "false" },
201+ ]
202+ expected_output = [
203+ BasicObject (pk = 1 , integer = 123 , boolean = True , private_field = "a" ),
204+ BasicObject (pk = 2 , integer = 456 , boolean = False , private_field = "b" ),
205+ ]
206+ serializer = ListUpdateSerializer (instance , data = input_data )
207+ assert serializer .is_valid ()
208+ updated_instances = serializer .save ()
209+ assert updated_instances == expected_output
210+
156211
157212class TestNestedListSerializer :
158213 """
@@ -481,7 +536,7 @@ class Serializer(serializers.Serializer):
481536 assert serializer .validated_data == {}
482537 assert serializer .errors == {}
483538
484- def test_udate_as_field_allow_empty_true (self ):
539+ def test_update_as_field_allow_empty_true (self ):
485540 class ListSerializer (serializers .Serializer ):
486541 update_field = serializers .IntegerField ()
487542 store_field = serializers .IntegerField ()
0 commit comments