Return Empty when getting listserializers from empty html input

If a non-required nested list serializer is *not* included in
postdata from an HTML form, the field validation nonetheless returns
an empty list.

This means you can easily clobber existing data when PUTting to
an existing resource, just by not including some list fields.

This is made worse by #3647, in which empty-body JSON requests will also
be treated as HTML forms, meaning any optional list fields will get
overwritten by an empty list.
This commit is contained in:
Craig de Stigter 2016-07-28 12:52:14 +12:00
parent 6a7d34ec34
commit 3ae711f3ab
2 changed files with 18 additions and 2 deletions

View File

@ -545,7 +545,7 @@ class ListSerializer(BaseSerializer):
# We override the default field access in order to support
# lists in HTML forms.
if html.is_html_input(dictionary):
return html.parse_html_list(dictionary, prefix=self.field_name)
return html.parse_html_list(dictionary, prefix=self.field_name) or empty
return dictionary.get(self.field_name, empty)
def run_validation(self, data=empty):

View File

@ -146,7 +146,7 @@ class TestNestedListSerializer:
def setup(self):
class TestSerializer(serializers.Serializer):
integers = serializers.ListSerializer(child=serializers.IntegerField())
integers = serializers.ListSerializer(child=serializers.IntegerField(), required=False)
booleans = serializers.ListSerializer(child=serializers.BooleanField())
def create(self, validated_data):
@ -221,6 +221,22 @@ class TestNestedListSerializer:
assert serializer.is_valid()
assert serializer.validated_data == expected_output
def test_validate_empty_html_input(self):
"""
When a field isn't present in HTML input, the field isn't included
in the output.
"""
input_data = MultiValueDict({
"booleans[0]": ["true"],
"booleans[1]": ["false"]
})
expected_output = {
"booleans": [True, False]
}
serializer = self.Serializer(data=input_data)
assert serializer.is_valid()
assert serializer.validated_data == expected_output
class TestNestedListOfListsSerializer:
def setup(self):