Fix read_only + default unique_together validation. (#5922)

* Add test for read_only + default unique_together validation.
* Fix read_only + default validation
This commit is contained in:
Carlton Gibson 2018-04-06 15:20:54 +02:00 committed by GitHub
parent 32caca4dd3
commit 42eb5a4342
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 0 deletions

View File

@ -441,6 +441,30 @@ class Serializer(BaseSerializer):
return value
def _read_only_defaults(self):
fields = [
field for field in self.fields.values()
if (field.read_only) and (field.default != empty) and (field.source != '*') and ('.' not in field.source)
]
defaults = OrderedDict()
for field in fields:
try:
default = field.get_default()
except SkipField:
continue
defaults[field.field_name] = default
return defaults
def run_validators(self, value):
"""
Add read_only fields with defaults to value before running validators.
"""
to_validate = self._read_only_defaults()
to_validate.update(value)
super(Serializer, self).run_validators(to_validate)
def to_internal_value(self, data):
"""
Dict of native values <- Dict of primitive datatypes.
@ -1477,6 +1501,12 @@ class ModelSerializer(Serializer):
if (field.source != '*') and ('.' not in field.source)
}
# Special Case: Add read_only fields with defaults.
field_names |= {
field.source for field in self.fields.values()
if (field.read_only) and (field.default != empty) and (field.source != '*') and ('.' not in field.source)
}
# Note that we make sure to check `unique_together` both on the
# base model class, but also on any parent classes.
validators = []

View File

@ -277,6 +277,30 @@ class TestUniquenessTogetherValidation(TestCase):
""")
assert repr(serializer) == expected
def test_read_only_fields_with_default(self):
"""
Special case of read_only + default DOES validate unique_together.
"""
class ReadOnlyFieldWithDefaultSerializer(serializers.ModelSerializer):
race_name = serializers.CharField(max_length=100, read_only=True, default='example')
class Meta:
model = UniquenessTogetherModel
fields = ('id', 'race_name', 'position')
data = {'position': 2}
serializer = ReadOnlyFieldWithDefaultSerializer(data=data)
assert len(serializer.validators) == 1
assert isinstance(serializer.validators[0], UniqueTogetherValidator)
assert serializer.validators[0].fields == ('race_name', 'position')
assert not serializer.is_valid()
assert serializer.errors == {
'non_field_errors': [
'The fields race_name, position must make a unique set.'
]
}
def test_allow_explict_override(self):
"""
Ensure validators can be explicitly removed..