Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

many=True, allow_null=True allows null instead of the list, not nulls in the list. #2766

Merged
merged 3 commits into from
Jul 31, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rest_framework/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
LIST_SERIALIZER_KWARGS = (
'read_only', 'write_only', 'required', 'default', 'initial', 'source',
'label', 'help_text', 'style', 'error_messages', 'allow_empty',
'instance', 'data', 'partial', 'context'
'instance', 'data', 'partial', 'context', 'allow_null'
)


Expand Down
56 changes: 56 additions & 0 deletions tests/test_serializer_nested.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,59 @@ def test_multipart_validate(self):
input_data = QueryDict('nested[one]=1')
serializer = self.Serializer(data=input_data)
assert serializer.is_valid()


class TestNestedSerializerWithMany:
def setup(self):
class NestedSerializer(serializers.Serializer):
example = serializers.IntegerField(max_value=10)

class TestSerializer(serializers.Serializer):
allow_null = NestedSerializer(many=True, allow_null=True)
not_allow_null = NestedSerializer(many=True)

self.Serializer = TestSerializer

def test_null_allowed_if_allow_null_is_set(self):
input_data = {
'allow_null': None,
'not_allow_null': [{'example': '2'}, {'example': '3'}]
}
expected_data = {
'allow_null': None,
'not_allow_null': [{'example': 2}, {'example': 3}]
}
serializer = self.Serializer(data=input_data)

assert serializer.is_valid(), serializer.errors
assert serializer.validated_data == expected_data

def test_null_is_not_allowed_if_allow_null_is_not_set(self):
input_data = {
'allow_null': None,
'not_allow_null': None
}
serializer = self.Serializer(data=input_data)

assert not serializer.is_valid()

expected_errors = {'not_allow_null': [serializer.error_messages['null']]}
assert serializer.errors == expected_errors

def test_run_the_field_validation_even_if_the_field_is_null(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move the serializer used to test this inside this test case to keep that complexity just inside this context.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the other two cases, but the motivation of this one is unclear to me.
Could you run me through an example of why this behavior is desired?
Alternatively, we could simply drop this test?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is exactly why I raised the problem in the first place. The idea is that if allow_null=True, then null is a valid value for the field so the validation mechanism should still call validate_field.

There can be use cases when you want to permit a null for a field only for one type of authenticated user/key and not for the other. Thus we need to run the validation method for the field in order to be able to have that functionality.

class TestSerializer(self.Serializer):
validation_was_run = False

def validate_allow_null(self, value):
TestSerializer.validation_was_run = True
return value

input_data = {
'allow_null': None,
'not_allow_null': [{'example': 2}]
}
serializer = TestSerializer(data=input_data)

assert serializer.is_valid()
assert serializer.validated_data == input_data
assert TestSerializer.validation_was_run