From d3430ce6d7c031499e30397e008aa06d5158af18 Mon Sep 17 00:00:00 2001 From: Andrew Backer Date: Tue, 13 Feb 2018 15:37:33 +0800 Subject: [PATCH] Allow for indexed keys in list field default value check (?field[0]=) --- rest_framework/fields.py | 3 ++- tests/test_fields.py | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 0684abfc2..ed34e5582 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1610,7 +1610,8 @@ class ListField(Field): # lists in HTML forms. if html.is_html_input(dictionary): if self.field_name not in dictionary: - return empty + if not any(k.startswith("%s[" % self.field_name) for k in dictionary): + return empty val = dictionary.getlist(self.field_name, []) if len(val) > 0: # Support QueryDict lists in HTML input. diff --git a/tests/test_fields.py b/tests/test_fields.py index 03613bbf9..e57e0ab43 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -472,6 +472,18 @@ class TestHTMLInput: assert serializer.is_valid() assert serializer.validated_data == {'a': 1, 'scores': [1, 3]} + def test_querydict_list_input_supports_indexed_keys(self): + """ + When data is passed in the format `scores[0]=1&scores[1]=3` + The field should return the correct list, ignoring the default + """ + class TestSerializer(serializers.Serializer): + scores = serializers.ListField(default=lambda: [1, 3]) + + serializer = TestSerializer(data=QueryDict("scores[0]=5&scores[1]=6")) + assert serializer.is_valid() + assert serializer.validated_data == {'scores': ['5', '6']} + def test_querydict_list_input_no_values_no_default_and_not_required(self): """ When there are no keys passed, there is no default, and required=False @@ -484,6 +496,19 @@ class TestHTMLInput: assert serializer.is_valid() assert serializer.validated_data == {} + def test_querydict_list_input_posts_key_but_no_values(self): + """ + When there are no keys passed, there is no default, and required=False + The field should return an array of 1 item, blank + * Not sure if this is desired behavior, but it is logical at least + """ + class TestSerializer(serializers.Serializer): + scores = serializers.ListField(required=False) + + serializer = TestSerializer(data=QueryDict('scores=&')) + assert serializer.is_valid() + assert serializer.validated_data == {'scores': ['']} + class TestCreateOnlyDefault: def setup(self):