mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-02-18 04:20:53 +03:00
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:
parent
32caca4dd3
commit
42eb5a4342
|
@ -441,6 +441,30 @@ class Serializer(BaseSerializer):
|
||||||
|
|
||||||
return value
|
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):
|
def to_internal_value(self, data):
|
||||||
"""
|
"""
|
||||||
Dict of native values <- Dict of primitive datatypes.
|
Dict of native values <- Dict of primitive datatypes.
|
||||||
|
@ -1477,6 +1501,12 @@ class ModelSerializer(Serializer):
|
||||||
if (field.source != '*') and ('.' not in field.source)
|
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
|
# Note that we make sure to check `unique_together` both on the
|
||||||
# base model class, but also on any parent classes.
|
# base model class, but also on any parent classes.
|
||||||
validators = []
|
validators = []
|
||||||
|
|
|
@ -277,6 +277,30 @@ class TestUniquenessTogetherValidation(TestCase):
|
||||||
""")
|
""")
|
||||||
assert repr(serializer) == expected
|
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):
|
def test_allow_explict_override(self):
|
||||||
"""
|
"""
|
||||||
Ensure validators can be explicitly removed..
|
Ensure validators can be explicitly removed..
|
||||||
|
|
Loading…
Reference in New Issue
Block a user