This commit is contained in:
Kamil Bar 2018-04-13 06:51:12 +00:00 committed by GitHub
commit 9c0e5c0ced
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 4 deletions

View File

@ -1604,12 +1604,15 @@ class ListField(Field):
self.validators.append(MinLengthValidator(self.min_length, message=message))
def get_value(self, dictionary):
if self.field_name not in dictionary:
if getattr(self.root, 'partial', False):
return empty
# We override the default field access in order to support
# lists in HTML forms.
if html.is_html_input(dictionary):
if getattr(self.root, 'partial', False):
if self.field_name not in dictionary:
regexp = re.compile(html.HTML_LIST_REGEXP_FORMAT % re.escape(self.field_name))
if not any(regexp.match(key) for key in dictionary.keys()):
return empty
val = dictionary.getlist(self.field_name, [])
if len(val) > 0:
# Support QueryDict lists in HTML input.

View File

@ -6,6 +6,9 @@ import re
from django.utils.datastructures import MultiValueDict
HTML_LIST_REGEXP_FORMAT = r'^%s\[([0-9]+)\](.*)$'
def is_html_input(dictionary):
# MultiDict type datastructures are used to represent HTML form input,
# which may have more than one value for each key.
@ -46,7 +49,7 @@ def parse_html_list(dictionary, prefix=''):
]
"""
ret = {}
regex = re.compile(r'^%s\[([0-9]+)\](.*)$' % re.escape(prefix))
regex = re.compile(HTML_LIST_REGEXP_FORMAT % re.escape(prefix))
for field, value in dictionary.items():
match = regex.match(field)
if not match:

View File

@ -466,6 +466,24 @@ class TestHTMLInput:
assert serializer.is_valid()
assert serializer.validated_data == {'scores': [1]}
def test_querydict_indexed_list_input(self):
class TestSerializer(serializers.Serializer):
scores = serializers.ListField(child=serializers.IntegerField())
instance = {'scores': []}
serializer = TestSerializer(instance=instance, data=QueryDict('scores[0]=1&scores[1]=3'), partial=True)
assert serializer.is_valid()
assert serializer.validated_data == {'scores': [1, 3]}
def test_querydict_indexed_list_input_only_one_input(self):
class TestSerializer(serializers.Serializer):
scores = serializers.ListField(child=serializers.IntegerField())
instance = {'scores': []}
serializer = TestSerializer(instance=instance, data=QueryDict('scores[0]=1'), partial=True)
assert serializer.is_valid()
assert serializer.validated_data == {'scores': [1]}
class TestCreateOnlyDefault:
def setup(self):