Skip to content

Commit be238f6

Browse files
Fix ListField.bind() to preserve explicit max_depth
Add condition check to prevent overriding explicit max_depth values. Includes 8 new test cases.
1 parent 31c867e commit be238f6

File tree

2 files changed

+138
-1
lines changed

2 files changed

+138
-1
lines changed

rest_framework/fields.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1680,7 +1680,7 @@ def __init__(self, **kwargs):
16801680

16811681
def bind(self, field_name, parent):
16821682
super().bind(field_name, parent)
1683-
if hasattr(parent, '_root_max_depth') and parent._root_max_depth is not None:
1683+
if self.max_depth is None and hasattr(parent, '_root_max_depth') and parent._root_max_depth is not None:
16841684
self._root_max_depth = parent._root_max_depth
16851685
self._current_depth = parent._current_depth + 1
16861686
self._propagate_depth_to_child()

tests/test_fields.py

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2876,6 +2876,143 @@ class Level1Serializer(serializers.Serializer):
28762876
field.run_validation([{'level2': {'level3': {'values': [1, 2]}}}])
28772877

28782878

2879+
class TestListFieldBindWithExplicitMaxDepth:
2880+
def test_child_listfield_keeps_explicit_max_depth_zero(self):
2881+
inner_list = serializers.ListField(
2882+
child=serializers.IntegerField(),
2883+
max_depth=0
2884+
)
2885+
outer_list = serializers.ListField(
2886+
child=inner_list,
2887+
max_depth=10
2888+
)
2889+
assert inner_list._root_max_depth == 0
2890+
with pytest.raises(serializers.ValidationError):
2891+
outer_list.run_validation([[1, 2]])
2892+
2893+
2894+
class TestListFieldBindWithoutExplicitMaxDepth:
2895+
def test_child_without_max_depth_inherits_from_parent(self):
2896+
inner_list = serializers.ListField(
2897+
child=serializers.IntegerField()
2898+
)
2899+
outer_list = serializers.ListField(
2900+
child=inner_list,
2901+
max_depth=3
2902+
)
2903+
assert inner_list._root_max_depth == 3
2904+
assert inner_list._current_depth == 1
2905+
output = outer_list.run_validation([[1, 2]])
2906+
assert output == [[1, 2]]
2907+
with pytest.raises(serializers.ValidationError):
2908+
outer_list.run_validation([[[[1]]]])
2909+
2910+
def test_multiple_children_some_inherit_some_explicit(self):
2911+
child_a = serializers.ListField(
2912+
child=serializers.IntegerField(),
2913+
max_depth=2
2914+
)
2915+
child_b = serializers.ListField(
2916+
child=serializers.IntegerField()
2917+
)
2918+
child_c = serializers.ListField(
2919+
child=serializers.IntegerField(),
2920+
max_depth=4
2921+
)
2922+
2923+
class MySerializerA(serializers.Serializer):
2924+
field = child_a
2925+
2926+
class MySerializerB(serializers.Serializer):
2927+
field = child_b
2928+
2929+
class MySerializerC(serializers.Serializer):
2930+
field = child_c
2931+
2932+
s_a = MySerializerA(max_depth=5)
2933+
s_b = MySerializerB(max_depth=5)
2934+
s_c = MySerializerC(max_depth=5)
2935+
2936+
assert s_a.fields['field']._root_max_depth == 2
2937+
assert s_b.fields['field']._root_max_depth == 5
2938+
assert s_c.fields['field']._root_max_depth == 4
2939+
2940+
2941+
class TestListFieldBindDepthPropagation:
2942+
def test_depth_propagation_through_multiple_levels(self):
2943+
level3 = serializers.ListField(child=serializers.IntegerField())
2944+
level2 = serializers.ListField(child=level3)
2945+
level1 = serializers.ListField(child=level2, max_depth=10)
2946+
2947+
assert level1._current_depth == 0
2948+
assert level2._current_depth == 1
2949+
assert level3._current_depth == 2
2950+
assert level1._root_max_depth == 10
2951+
assert level2._root_max_depth == 10
2952+
assert level3._root_max_depth == 10
2953+
2954+
2955+
class TestListFieldBindWithDictField:
2956+
def test_listfield_child_of_dictfield_keeps_explicit_max_depth(self):
2957+
list_field = serializers.ListField(
2958+
child=serializers.IntegerField(),
2959+
max_depth=2
2960+
)
2961+
dict_field = serializers.DictField(
2962+
child=list_field,
2963+
max_depth=10
2964+
)
2965+
assert dict_field.child._root_max_depth == 2
2966+
output = dict_field.run_validation({'key': [1, 2]})
2967+
assert output == {'key': [1, 2]}
2968+
with pytest.raises(serializers.ValidationError):
2969+
dict_field.run_validation({'key': [[1, 2]]})
2970+
2971+
2972+
class TestListFieldBindWithSerializers:
2973+
def test_listfield_in_serializer_with_explicit_max_depth(self):
2974+
class MySerializer(serializers.Serializer):
2975+
explicit_field = serializers.ListField(
2976+
child=serializers.IntegerField(),
2977+
max_depth=2
2978+
)
2979+
inherit_field = serializers.ListField(
2980+
child=serializers.IntegerField()
2981+
)
2982+
2983+
serializer = MySerializer(max_depth=5)
2984+
assert serializer.fields['explicit_field']._root_max_depth == 2
2985+
assert serializer.fields['inherit_field']._root_max_depth == 5
2986+
2987+
def test_nested_serializers_with_listfield(self):
2988+
class InnerSerializer(serializers.Serializer):
2989+
values = serializers.ListField(
2990+
child=serializers.IntegerField(),
2991+
max_depth=3
2992+
)
2993+
2994+
class OuterSerializer(serializers.Serializer):
2995+
inner = InnerSerializer(max_depth=10)
2996+
2997+
serializer = OuterSerializer(max_depth=20)
2998+
values_field = serializer.fields['inner'].fields['values']
2999+
assert values_field._root_max_depth == 3
3000+
3001+
3002+
class TestListFieldBindEdgeCases:
3003+
def test_field_max_depth_one(self):
3004+
inner = serializers.ListField(
3005+
child=serializers.IntegerField(),
3006+
max_depth=1
3007+
)
3008+
outer = serializers.ListField(child=inner, max_depth=10)
3009+
assert inner._root_max_depth == 1
3010+
output = outer.run_validation([[1, 2, 3]])
3011+
assert output == [[1, 2, 3]]
3012+
with pytest.raises(serializers.ValidationError):
3013+
outer.run_validation([[[1]]])
3014+
3015+
28793016
class TestHStoreField(FieldValues):
28803017
"""
28813018
Values for `ListField` with CharField as child.

0 commit comments

Comments
 (0)