Skip to content
19 changes: 16 additions & 3 deletions rest_framework/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ def set_context(self, serializer):
"""
# Determine the existing instance, if this is an update operation.
self.instance = getattr(serializer, 'instance', None)
self.serializer = serializer

def enforce_required_fields(self, attrs):
"""
Expand All @@ -133,12 +134,24 @@ def filter_queryset(self, attrs, queryset):
if self.instance is not None:
for field_name in self.fields:
if field_name not in attrs:
attrs[field_name] = getattr(self.instance, field_name)
if field_name == self.serializer.fields[field_name].source:
attrs[field_name] = getattr(self.instance, field_name)
else:
attrs[self.serializer.fields[field_name].source] = getattr(self.instance, self.serializer.fields[field_name].source)


# Determine the filter keyword arguments and filter the queryset.
filter_kwargs = {
field_name: attrs[field_name]
for field_name in self.fields
(
field_name
if field_name == self.serializer.fields[field_name].source
else self.serializer.fields[field_name].source
): (
attrs[field_name]
if self.instance is None or not self.serializer.partial
else attrs[self.serializer.fields[field_name].source]
)
for field_name in self.fields
}
return qs_filter(queryset, **filter_kwargs)

Expand Down
34 changes: 34 additions & 0 deletions tests/test_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,40 @@ def filter(self, **kwargs):
validator.filter_queryset(attrs=data, queryset=queryset)
assert queryset.called_with == {'race_name': 'bar', 'position': 1}

class WritableFieldsWithSourceSerializer(serializers.ModelSerializer):
name = serializers.CharField(source='race_name')

class Meta:
model = UniquenessTogetherModel
fields = ['name', 'position']
validators = [
UniqueTogetherValidator(
queryset=UniquenessTogetherModel.objects.all(),
fields=['name', 'position']
)
]

class ReadOnlyFieldsWithSourceSerializer(serializers.ModelSerializer):
name = serializers.CharField(source='race_name', read_only=True, default='test')

class Meta:
model = UniquenessTogetherModel
fields = ['name', 'position']
validators = [
UniqueTogetherValidator(
queryset=UniquenessTogetherModel.objects.all(),
fields=['name', 'position']
)
]

class TestFieldsWithFieldSource(TestCase):
def test_writeable(self):
serializer = WritableFieldsWithSourceSerializer(data={'name': 'formula1', 'position': '1'})
serializer.is_valid(raise_exception=True)

def test_read_only(self):
serializer = ReadOnlyFieldsWithSourceSerializer(data={'position': '1'})
serializer.is_valid(raise_exception=True)

# Tests for `UniqueForDateValidator`
# ----------------------------------
Expand Down