@@ -442,7 +442,7 @@ class CommunitySerializer(serializers.Serializer):
442442 'colors' : ['#ffffff' , '#000000' ]
443443 })
444444 serializer = CommunitySerializer (data = data , partial = True )
445- assert serializer .is_valid (), f"Expected valid but got errors: { serializer . errors } "
445+ assert serializer .is_valid ()
446446 assert 'colors' in serializer .validated_data
447447 assert serializer .validated_data ['colors' ] == ['#ffffff' , '#000000' ]
448448
@@ -462,10 +462,71 @@ class CommunitySerializer(serializers.Serializer):
462462 'colors[1]' : ['#000000' ]
463463 })
464464 serializer = CommunitySerializer (data = data , partial = False )
465- assert serializer .is_valid (), f"Expected valid but got errors: { serializer . errors } "
465+ assert serializer .is_valid ()
466466 assert 'colors' in serializer .validated_data
467467 assert serializer .validated_data ['colors' ] == ['#ffffff' , '#000000' ]
468468
469+ def test_listfield_mixed_plain_and_indexed_keys (self ):
470+ """
471+ Test that when both plain field and indexed keys are present,
472+ the plain field takes precedence (standard HTML form behavior).
473+ """
474+ class CommunitySerializer (serializers .Serializer ):
475+ colors = serializers .ListField (
476+ allow_null = True ,
477+ child = serializers .CharField (label = 'Colors' , max_length = 7 ),
478+ required = False
479+ )
480+ # When both present, getlist should win (standard HTML form behavior)
481+ data = MultiValueDict ({
482+ 'colors' : ['#aaaaaa' , '#bbbbbb' ], # This should be used
483+ 'colors[0]' : ['#ffffff' ], # These should be ignored
484+ 'colors[1]' : ['#000000' ]
485+ })
486+ serializer = CommunitySerializer (data = data , partial = True )
487+ assert serializer .is_valid ()
488+ assert 'colors' in serializer .validated_data
489+ # Plain field values should take precedence
490+ assert serializer .validated_data ['colors' ] == ['#aaaaaa' , '#bbbbbb' ]
491+
492+ def test_partial_listfield_no_data_returns_empty (self ):
493+ """
494+ Test that when a ListField is omitted in partial updates,
495+ it does not appear in validated_data (not even as an empty list).
496+ """
497+ class CommunitySerializer (serializers .Serializer ):
498+ name = serializers .CharField (max_length = 100 )
499+ colors = serializers .ListField (
500+ allow_null = True ,
501+ child = serializers .CharField (label = 'Colors' , max_length = 7 ),
502+ required = False
503+ )
504+ data = MultiValueDict ({
505+ 'name' : ['Community Name' ]
506+ })
507+ serializer = CommunitySerializer (data = data , partial = True )
508+ assert serializer .is_valid ()
509+ assert 'name' in serializer .validated_data
510+ assert 'colors' not in serializer .validated_data # Should be skipped
511+
512+ def test_non_partial_listfield_standard_submission (self ):
513+ """
514+ Test standard HTML form list submission without partial=True.
515+ Ensures backward compatibility with existing behavior.
516+ """
517+ class CommunitySerializer (serializers .Serializer ):
518+ colors = serializers .ListField (
519+ child = serializers .CharField (label = 'Colors' , max_length = 7 ),
520+ required = True
521+ )
522+ # Standard multi-select form submission
523+ data = MultiValueDict ({
524+ 'colors' : ['#ffffff' , '#000000' , '#ff0000' ]
525+ })
526+ serializer = CommunitySerializer (data = data , partial = False )
527+ assert serializer .is_valid ()
528+ assert serializer .validated_data ['colors' ] == ['#ffffff' , '#000000' , '#ff0000' ]
529+
469530 def test_allow_empty_true (self ):
470531 class ListSerializer (serializers .Serializer ):
471532 update_field = serializers .IntegerField ()
0 commit comments