Skip to content

Commit e454758

Browse files
authored
Fix regression in unique_together validation with SerializerMethodField (#9712)
1 parent 33d59fe commit e454758

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-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: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,43 @@ 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_method_field(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+
def test_uniq_together_validation_uses_model_fields_with_source_field(self):
539+
class TestSerializer(serializers.ModelSerializer):
540+
pos = serializers.IntegerField(source='position')
541+
542+
class Meta:
543+
model = NullUniquenessTogetherModel
544+
fields = ['race_name', 'pos']
545+
546+
serializer = TestSerializer()
547+
expected = dedent("""
548+
TestSerializer():
549+
race_name = CharField(max_length=100, required=True)
550+
pos = IntegerField(source='position')
551+
class Meta:
552+
validators = [<UniqueTogetherValidator(queryset=NullUniquenessTogetherModel.objects.all(), fields=('race_name', 'pos'))>]
553+
""")
554+
assert repr(serializer) == expected
555+
519556

520557
class UniqueConstraintModel(models.Model):
521558
race_name = models.CharField(max_length=100)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy