mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-12-01 22:14:06 +03:00
Merge pull request #4222 from NewVadim/master
Fix partial update for the ListSerializer.
This commit is contained in:
commit
dea601dc86
|
@ -565,6 +565,10 @@ class ListSerializer(BaseSerializer):
|
||||||
super(ListSerializer, self).__init__(*args, **kwargs)
|
super(ListSerializer, self).__init__(*args, **kwargs)
|
||||||
self.child.bind(field_name='', parent=self)
|
self.child.bind(field_name='', parent=self)
|
||||||
|
|
||||||
|
def bind(self, field_name, parent):
|
||||||
|
super(ListSerializer, self).bind(field_name, parent)
|
||||||
|
self.partial = self.parent.partial
|
||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
if hasattr(self, 'initial_data'):
|
if hasattr(self, 'initial_data'):
|
||||||
return self.to_representation(self.initial_data)
|
return self.to_representation(self.initial_data)
|
||||||
|
@ -616,6 +620,9 @@ class ListSerializer(BaseSerializer):
|
||||||
}, code='not_a_list')
|
}, code='not_a_list')
|
||||||
|
|
||||||
if not self.allow_empty and len(data) == 0:
|
if not self.allow_empty and len(data) == 0:
|
||||||
|
if self.parent and self.partial:
|
||||||
|
raise SkipField()
|
||||||
|
|
||||||
message = self.error_messages['empty']
|
message = self.error_messages['empty']
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
api_settings.NON_FIELD_ERRORS_KEY: [message]
|
api_settings.NON_FIELD_ERRORS_KEY: [message]
|
||||||
|
|
|
@ -318,3 +318,217 @@ class TestSerializerPartialUsage:
|
||||||
assert serializer.is_valid()
|
assert serializer.is_valid()
|
||||||
assert serializer.validated_data == {}
|
assert serializer.validated_data == {}
|
||||||
assert serializer.errors == {}
|
assert serializer.errors == {}
|
||||||
|
|
||||||
|
def test_allow_empty_true(self):
|
||||||
|
class ListSerializer(serializers.Serializer):
|
||||||
|
update_field = serializers.IntegerField()
|
||||||
|
store_field = serializers.IntegerField()
|
||||||
|
|
||||||
|
instance = [
|
||||||
|
{'update_field': 11, 'store_field': 12},
|
||||||
|
{'update_field': 21, 'store_field': 22},
|
||||||
|
]
|
||||||
|
|
||||||
|
serializer = ListSerializer(instance, data=[], partial=True, many=True)
|
||||||
|
assert serializer.is_valid()
|
||||||
|
assert serializer.validated_data == []
|
||||||
|
assert serializer.errors == []
|
||||||
|
|
||||||
|
def test_update_allow_empty_true(self):
|
||||||
|
class ListSerializer(serializers.Serializer):
|
||||||
|
update_field = serializers.IntegerField()
|
||||||
|
store_field = serializers.IntegerField()
|
||||||
|
|
||||||
|
instance = [
|
||||||
|
{'update_field': 11, 'store_field': 12},
|
||||||
|
{'update_field': 21, 'store_field': 22},
|
||||||
|
]
|
||||||
|
input_data = [{'update_field': 31}, {'update_field': 41}]
|
||||||
|
updated_data_list = [
|
||||||
|
{'update_field': 31, 'store_field': 12},
|
||||||
|
{'update_field': 41, 'store_field': 22},
|
||||||
|
]
|
||||||
|
|
||||||
|
serializer = ListSerializer(
|
||||||
|
instance, data=input_data, partial=True, many=True)
|
||||||
|
assert serializer.is_valid()
|
||||||
|
|
||||||
|
for index, data in enumerate(serializer.validated_data):
|
||||||
|
for key, value in data.items():
|
||||||
|
assert value == updated_data_list[index][key]
|
||||||
|
|
||||||
|
assert serializer.errors == []
|
||||||
|
|
||||||
|
def test_allow_empty_false(self):
|
||||||
|
class ListSerializer(serializers.Serializer):
|
||||||
|
update_field = serializers.IntegerField()
|
||||||
|
store_field = serializers.IntegerField()
|
||||||
|
|
||||||
|
instance = [
|
||||||
|
{'update_field': 11, 'store_field': 12},
|
||||||
|
{'update_field': 21, 'store_field': 22},
|
||||||
|
]
|
||||||
|
|
||||||
|
serializer = ListSerializer(
|
||||||
|
instance, data=[], allow_empty=False, partial=True, many=True)
|
||||||
|
assert not serializer.is_valid()
|
||||||
|
assert serializer.validated_data == []
|
||||||
|
assert len(serializer.errors) == 1
|
||||||
|
assert serializer.errors['non_field_errors'][0] == 'This list may not be empty.'
|
||||||
|
|
||||||
|
def test_update_allow_empty_false(self):
|
||||||
|
class ListSerializer(serializers.Serializer):
|
||||||
|
update_field = serializers.IntegerField()
|
||||||
|
store_field = serializers.IntegerField()
|
||||||
|
|
||||||
|
instance = [
|
||||||
|
{'update_field': 11, 'store_field': 12},
|
||||||
|
{'update_field': 21, 'store_field': 22},
|
||||||
|
]
|
||||||
|
input_data = [{'update_field': 31}, {'update_field': 41}]
|
||||||
|
updated_data_list = [
|
||||||
|
{'update_field': 31, 'store_field': 12},
|
||||||
|
{'update_field': 41, 'store_field': 22},
|
||||||
|
]
|
||||||
|
|
||||||
|
serializer = ListSerializer(
|
||||||
|
instance, data=input_data, allow_empty=False, partial=True, many=True)
|
||||||
|
assert serializer.is_valid()
|
||||||
|
|
||||||
|
for index, data in enumerate(serializer.validated_data):
|
||||||
|
for key, value in data.items():
|
||||||
|
assert value == updated_data_list[index][key]
|
||||||
|
|
||||||
|
assert serializer.errors == []
|
||||||
|
|
||||||
|
def test_as_field_allow_empty_true(self):
|
||||||
|
class ListSerializer(serializers.Serializer):
|
||||||
|
update_field = serializers.IntegerField()
|
||||||
|
store_field = serializers.IntegerField()
|
||||||
|
|
||||||
|
class Serializer(serializers.Serializer):
|
||||||
|
extra_field = serializers.IntegerField()
|
||||||
|
list_field = ListSerializer(many=True)
|
||||||
|
|
||||||
|
instance = {
|
||||||
|
'extra_field': 1,
|
||||||
|
'list_field': [
|
||||||
|
{'update_field': 11, 'store_field': 12},
|
||||||
|
{'update_field': 21, 'store_field': 22},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
serializer = Serializer(instance, data={}, partial=True)
|
||||||
|
assert serializer.is_valid()
|
||||||
|
assert serializer.validated_data == {}
|
||||||
|
assert serializer.errors == {}
|
||||||
|
|
||||||
|
def test_udate_as_field_allow_empty_true(self):
|
||||||
|
class ListSerializer(serializers.Serializer):
|
||||||
|
update_field = serializers.IntegerField()
|
||||||
|
store_field = serializers.IntegerField()
|
||||||
|
|
||||||
|
class Serializer(serializers.Serializer):
|
||||||
|
extra_field = serializers.IntegerField()
|
||||||
|
list_field = ListSerializer(many=True)
|
||||||
|
|
||||||
|
instance = {
|
||||||
|
'extra_field': 1,
|
||||||
|
'list_field': [
|
||||||
|
{'update_field': 11, 'store_field': 12},
|
||||||
|
{'update_field': 21, 'store_field': 22},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
input_data_1 = {'extra_field': 2}
|
||||||
|
input_data_2 = {
|
||||||
|
'list_field': [
|
||||||
|
{'update_field': 31},
|
||||||
|
{'update_field': 41},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# data_1
|
||||||
|
serializer = Serializer(instance, data=input_data_1, partial=True)
|
||||||
|
assert serializer.is_valid()
|
||||||
|
assert len(serializer.validated_data) == 1
|
||||||
|
assert serializer.validated_data['extra_field'] == 2
|
||||||
|
assert serializer.errors == {}
|
||||||
|
|
||||||
|
# data_2
|
||||||
|
serializer = Serializer(instance, data=input_data_2, partial=True)
|
||||||
|
assert serializer.is_valid()
|
||||||
|
|
||||||
|
updated_data_list = [
|
||||||
|
{'update_field': 31, 'store_field': 12},
|
||||||
|
{'update_field': 41, 'store_field': 22},
|
||||||
|
]
|
||||||
|
for index, data in enumerate(serializer.validated_data['list_field']):
|
||||||
|
for key, value in data.items():
|
||||||
|
assert value == updated_data_list[index][key]
|
||||||
|
|
||||||
|
assert serializer.errors == {}
|
||||||
|
|
||||||
|
def test_as_field_allow_empty_false(self):
|
||||||
|
class ListSerializer(serializers.Serializer):
|
||||||
|
update_field = serializers.IntegerField()
|
||||||
|
store_field = serializers.IntegerField()
|
||||||
|
|
||||||
|
class Serializer(serializers.Serializer):
|
||||||
|
extra_field = serializers.IntegerField()
|
||||||
|
list_field = ListSerializer(many=True, allow_empty=False)
|
||||||
|
|
||||||
|
instance = {
|
||||||
|
'extra_field': 1,
|
||||||
|
'list_field': [
|
||||||
|
{'update_field': 11, 'store_field': 12},
|
||||||
|
{'update_field': 21, 'store_field': 22},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
serializer = Serializer(instance, data={}, partial=True)
|
||||||
|
assert serializer.is_valid()
|
||||||
|
assert serializer.validated_data == {}
|
||||||
|
assert serializer.errors == {}
|
||||||
|
|
||||||
|
def test_update_as_field_allow_empty_false(self):
|
||||||
|
class ListSerializer(serializers.Serializer):
|
||||||
|
update_field = serializers.IntegerField()
|
||||||
|
store_field = serializers.IntegerField()
|
||||||
|
|
||||||
|
class Serializer(serializers.Serializer):
|
||||||
|
extra_field = serializers.IntegerField()
|
||||||
|
list_field = ListSerializer(many=True, allow_empty=False)
|
||||||
|
|
||||||
|
instance = {
|
||||||
|
'extra_field': 1,
|
||||||
|
'list_field': [
|
||||||
|
{'update_field': 11, 'store_field': 12},
|
||||||
|
{'update_field': 21, 'store_field': 22},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
input_data_1 = {'extra_field': 2}
|
||||||
|
input_data_2 = {
|
||||||
|
'list_field': [
|
||||||
|
{'update_field': 31},
|
||||||
|
{'update_field': 41},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
updated_data_list = [
|
||||||
|
{'update_field': 31, 'store_field': 12},
|
||||||
|
{'update_field': 41, 'store_field': 22},
|
||||||
|
]
|
||||||
|
|
||||||
|
# data_1
|
||||||
|
serializer = Serializer(instance, data=input_data_1, partial=True)
|
||||||
|
assert serializer.is_valid()
|
||||||
|
assert serializer.errors == {}
|
||||||
|
|
||||||
|
# data_2
|
||||||
|
serializer = Serializer(instance, data=input_data_2, partial=True)
|
||||||
|
assert serializer.is_valid()
|
||||||
|
|
||||||
|
for index, data in enumerate(serializer.validated_data['list_field']):
|
||||||
|
for key, value in data.items():
|
||||||
|
assert value == updated_data_list[index][key]
|
||||||
|
|
||||||
|
assert serializer.errors == {}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user