Skip to content

Commit b80642a

Browse files
committed
Fix unique together validation.
While building validator unique together fields were compared with declared field names instead of model field names
1 parent 33d59fe commit b80642a

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

rest_framework/serializers.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1469,12 +1469,13 @@ def get_uniqueness_extra_kwargs(self, field_names, declared_fields, extra_kwargs
14691469
model_field.unique_for_year}
14701470

14711471
unique_constraint_names -= {None}
1472+
model_fields_names = set(model_fields.keys())
14721473

14731474
# Include each of the `unique_together` and `UniqueConstraint` field names,
14741475
# so long as all the field names are included on the serializer.
14751476
for unique_together_list, queryset, condition_fields, condition in self.get_unique_together_constraints(model):
14761477
unique_together_list_and_condition_fields = set(unique_together_list) | set(condition_fields)
1477-
if set(field_names).issuperset(unique_together_list_and_condition_fields):
1478+
if model_fields_names.issuperset(unique_together_list_and_condition_fields):
14781479
unique_constraint_names |= unique_together_list_and_condition_fields
14791480

14801481
# Now we have all the field names that have uniqueness constraints

tests/test_validators.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,44 @@ def filter(self, **kwargs):
516516
validator.filter_queryset(attrs=data, queryset=queryset, serializer=serializer)
517517
assert queryset.called_with == {'race_name': 'bar', 'position': 1}
518518

519+
def test_uniq_together_validation_uses_model_fields(self):
520+
class TestSerializer(serializers.ModelSerializer):
521+
position = serializers.SerializerMethodField()
522+
523+
def get_position(self, obj):
524+
return obj.position or 0
525+
526+
class Meta:
527+
model = NullUniquenessTogetherModel
528+
fields = ['race_name', 'position']
529+
530+
serializer = TestSerializer()
531+
expected = dedent("""
532+
TestSerializer():
533+
race_name = CharField(max_length=100)
534+
position = SerializerMethodField()
535+
""")
536+
assert repr(serializer) == expected
537+
538+
class Test2Serializer(serializers.ModelSerializer):
539+
pos = serializers.IntegerField(source='position')
540+
541+
class Meta:
542+
model = NullUniquenessTogetherModel
543+
fields = ['race_name', 'pos']
544+
545+
serializer = Test2Serializer()
546+
expected = dedent("""
547+
Test2Serializer():
548+
race_name = CharField(max_length=100, required=True)
549+
pos = IntegerField(source='position')
550+
class Meta:
551+
validators = [<UniqueTogetherValidator(queryset=NullUniquenessTogetherModel.objects.all(), fields=('race_name', 'pos'))>]
552+
""")
553+
assert repr(serializer) == expected
554+
555+
556+
519557

520558
class UniqueConstraintModel(models.Model):
521559
race_name = models.CharField(max_length=100)

0 commit comments

Comments
 (0)