Skip to content

Commit 518eb22

Browse files
authored
Fix unique_together validation with source (#9482)
1 parent 8e304e1 commit 518eb22

File tree

2 files changed

+29
-6
lines changed

2 files changed

+29
-6
lines changed

rest_framework/validators.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,17 +159,18 @@ def __call__(self, attrs, serializer):
159159
queryset = self.filter_queryset(attrs, queryset, serializer)
160160
queryset = self.exclude_current_instance(attrs, queryset, serializer.instance)
161161

162+
checked_names = [
163+
serializer.fields[field_name].source for field_name in self.fields
164+
]
162165
# Ignore validation if any field is None
163166
if serializer.instance is None:
164-
checked_values = [
165-
value for field, value in attrs.items() if field in self.fields
166-
]
167+
checked_values = [attrs[field_name] for field_name in checked_names]
167168
else:
168169
# Ignore validation if all field values are unchanged
169170
checked_values = [
170-
value
171-
for field, value in attrs.items()
172-
if field in self.fields and value != getattr(serializer.instance, field)
171+
attrs[field_name]
172+
for field_name in checked_names
173+
if attrs[field_name] != getattr(serializer.instance, field_name)
173174
]
174175

175176
if checked_values and None not in checked_values and qs_exists(queryset):

tests/test_validators.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,28 @@ def test_ignore_validation_for_unchanged_fields(self):
469469
assert serializer.is_valid()
470470
assert not mock.called
471471

472+
@patch("rest_framework.validators.qs_exists")
473+
def test_unique_together_with_source(self, mock_qs_exists):
474+
class UniqueTogetherWithSourceSerializer(serializers.ModelSerializer):
475+
name = serializers.CharField(source="race_name")
476+
pos = serializers.IntegerField(source="position")
477+
478+
class Meta:
479+
model = UniquenessTogetherModel
480+
fields = ["name", "pos"]
481+
482+
data = {"name": "Paris Marathon", "pos": 1}
483+
instance = UniquenessTogetherModel.objects.create(
484+
race_name="Paris Marathon", position=1
485+
)
486+
serializer = UniqueTogetherWithSourceSerializer(data=data)
487+
assert not serializer.is_valid()
488+
assert mock_qs_exists.called
489+
mock_qs_exists.reset_mock()
490+
serializer = UniqueTogetherWithSourceSerializer(data=data, instance=instance)
491+
assert serializer.is_valid()
492+
assert not mock_qs_exists.called
493+
472494
def test_filter_queryset_do_not_skip_existing_attribute(self):
473495
"""
474496
filter_queryset should add value from existing instance attribute

0 commit comments

Comments
 (0)