Fix regression in unique_together validation with SerializerMethodField (#9712)

This commit is contained in:
Konstantin Alekseev 2025-06-10 14:47:28 +03:00 committed by GitHub
parent 33d59fefaa
commit e454758fb6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 39 additions and 1 deletions

View File

@ -1469,12 +1469,13 @@ class ModelSerializer(Serializer):
model_field.unique_for_year}
unique_constraint_names -= {None}
model_fields_names = set(model_fields.keys())
# Include each of the `unique_together` and `UniqueConstraint` field names,
# so long as all the field names are included on the serializer.
for unique_together_list, queryset, condition_fields, condition in self.get_unique_together_constraints(model):
unique_together_list_and_condition_fields = set(unique_together_list) | set(condition_fields)
if set(field_names).issuperset(unique_together_list_and_condition_fields):
if model_fields_names.issuperset(unique_together_list_and_condition_fields):
unique_constraint_names |= unique_together_list_and_condition_fields
# Now we have all the field names that have uniqueness constraints

View File

@ -516,6 +516,43 @@ class TestUniquenessTogetherValidation(TestCase):
validator.filter_queryset(attrs=data, queryset=queryset, serializer=serializer)
assert queryset.called_with == {'race_name': 'bar', 'position': 1}
def test_uniq_together_validation_uses_model_fields_method_field(self):
class TestSerializer(serializers.ModelSerializer):
position = serializers.SerializerMethodField()
def get_position(self, obj):
return obj.position or 0
class Meta:
model = NullUniquenessTogetherModel
fields = ['race_name', 'position']
serializer = TestSerializer()
expected = dedent("""
TestSerializer():
race_name = CharField(max_length=100)
position = SerializerMethodField()
""")
assert repr(serializer) == expected
def test_uniq_together_validation_uses_model_fields_with_source_field(self):
class TestSerializer(serializers.ModelSerializer):
pos = serializers.IntegerField(source='position')
class Meta:
model = NullUniquenessTogetherModel
fields = ['race_name', 'pos']
serializer = TestSerializer()
expected = dedent("""
TestSerializer():
race_name = CharField(max_length=100, required=True)
pos = IntegerField(source='position')
class Meta:
validators = [<UniqueTogetherValidator(queryset=NullUniquenessTogetherModel.objects.all(), fields=('race_name', 'pos'))>]
""")
assert repr(serializer) == expected
class UniqueConstraintModel(models.Model):
race_name = models.CharField(max_length=100)