From 55f6427ef4dbbc8a290763582567f61cb30754e2 Mon Sep 17 00:00:00 2001 From: Andrew Backer Date: Wed, 7 Feb 2018 12:45:33 +0800 Subject: [PATCH 1/2] Fix support for ListField default values in HTML mode The ListField handles html forms data differently than json data. This section would always return a value (an empty list) for a list field, even when that field name was not posted at all. This change checks for the field being present and returns `empty` if it is not; this lets the standard default-value and required field handling take over. --- rest_framework/fields.py | 2 ++ tests/test_fields.py | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index a336528e85..0684abfc2f 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1609,6 +1609,8 @@ def get_value(self, dictionary): # We override the default field access in order to support # lists in HTML forms. if html.is_html_input(dictionary): + if self.field_name not 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 35593a2833..03613bbf94 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -459,6 +459,31 @@ class TestSerializer(serializers.Serializer): assert serializer.is_valid() assert serializer.validated_data == {'scores': [1]} + def test_querydict_list_input_no_values_uses_default(self): + """ + When there are no values passed in, and default is set + The field should return the default value + """ + class TestSerializer(serializers.Serializer): + a = serializers.IntegerField(required=True) + scores = serializers.ListField(default=lambda: [1, 3]) + + serializer = TestSerializer(data=QueryDict('a=1&')) + assert serializer.is_valid() + assert serializer.validated_data == {'a': 1, 'scores': [1, 3]} + + 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 + The field should be skipped + """ + class TestSerializer(serializers.Serializer): + scores = serializers.ListField(required=False) + + serializer = TestSerializer(data=QueryDict('')) + assert serializer.is_valid() + assert serializer.validated_data == {} + class TestCreateOnlyDefault: def setup(self): From d3430ce6d7c031499e30397e008aa06d5158af18 Mon Sep 17 00:00:00 2001 From: Andrew Backer Date: Tue, 13 Feb 2018 15:37:33 +0800 Subject: [PATCH 2/2] 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 0684abfc2f..ed34e5582c 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1610,7 +1610,8 @@ def get_value(self, dictionary): # 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 03613bbf94..e57e0ab43c 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -472,6 +472,18 @@ class TestSerializer(serializers.Serializer): 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 TestSerializer(serializers.Serializer): 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): pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy