Skip to content

fixing unique together validator for fields with source #7005

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

Closed
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