From d4e404397c569c09fb72c30c1c23a9a8cce175f5 Mon Sep 17 00:00:00 2001 From: Konstantin Alekseev Date: Sat, 31 May 2025 17:59:51 +0300 Subject: [PATCH] Fix unique together validation. While building validator unique together fields were compared with declared field names instead of model field names --- rest_framework/serializers.py | 3 ++- tests/test_validators.py | 37 +++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 0b87aa8fc1..8fe284bc84 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -1469,12 +1469,13 @@ def get_uniqueness_extra_kwargs(self, field_names, declared_fields, extra_kwargs 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 diff --git a/tests/test_validators.py b/tests/test_validators.py index d19734d98c..c594eecbe5 100644 --- a/tests/test_validators.py +++ b/tests/test_validators.py @@ -516,6 +516,43 @@ def filter(self, **kwargs): 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 = [] + """) + assert repr(serializer) == expected + class UniqueConstraintModel(models.Model): race_name = models.CharField(max_length=100) 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