Skip to content

Commit 513ddb4

Browse files
authored
Condition of UniqueTogetherValidator can be read-only (#9764)
* Condition of UniqueValidator can be read-only We can't always expect to find the value of the condition in the serializer if the field is read-only. * Reproducible test
1 parent c8b6d3d commit 513ddb4

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

rest_framework/validators.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,12 @@ def __call__(self, attrs, serializer):
189189
]
190190

191191
condition_sources = (serializer.fields[field_name].source for field_name in self.condition_fields)
192-
condition_kwargs = {source: attrs[source] for source in condition_sources}
192+
condition_kwargs = {
193+
source: attrs[source]
194+
if source in attrs
195+
else getattr(serializer.instance, source)
196+
for source in condition_sources
197+
}
193198
if checked_values and None not in checked_values and qs_exists_with_condition(queryset, self.condition, condition_kwargs):
194199
field_names = ', '.join(self.fields)
195200
message = self.message.format(field_names=field_names)

tests/test_validators.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,21 @@ class Meta:
589589
]
590590

591591

592+
class UniqueConstraintReadOnlyFieldModel(models.Model):
593+
state = models.CharField(max_length=100, default="new")
594+
position = models.IntegerField()
595+
something = models.IntegerField()
596+
597+
class Meta:
598+
constraints = [
599+
models.UniqueConstraint(
600+
name="unique_constraint_%(class)s",
601+
fields=("position", "something"),
602+
condition=models.Q(state="new"),
603+
),
604+
]
605+
606+
592607
class UniqueConstraintNullableModel(models.Model):
593608
title = models.CharField(max_length=100)
594609
age = models.IntegerField(null=True)
@@ -738,6 +753,31 @@ class Meta:
738753
)
739754
assert serializer.is_valid()
740755

756+
def test_uniq_constraint_condition_read_only_create(self):
757+
class UniqueConstraintReadOnlyFieldModelSerializer(serializers.ModelSerializer):
758+
class Meta:
759+
model = UniqueConstraintReadOnlyFieldModel
760+
read_only_fields = ("state",)
761+
fields = ("position", "something", *read_only_fields)
762+
serializer = UniqueConstraintReadOnlyFieldModelSerializer(
763+
data={"position": 1, "something": 1}
764+
)
765+
assert serializer.is_valid()
766+
767+
def test_uniq_constraint_condition_read_only_partial(self):
768+
class UniqueConstraintReadOnlyFieldModelSerializer(serializers.ModelSerializer):
769+
class Meta:
770+
model = UniqueConstraintReadOnlyFieldModel
771+
read_only_fields = ("state",)
772+
fields = ("position", "something", *read_only_fields)
773+
instance = UniqueConstraintReadOnlyFieldModel.objects.create(position=1, something=1)
774+
serializer = UniqueConstraintReadOnlyFieldModelSerializer(
775+
instance=instance,
776+
data={"position": 1, "something": 1},
777+
partial=True
778+
)
779+
assert serializer.is_valid()
780+
741781

742782
# Tests for `UniqueForDateValidator`
743783
# ----------------------------------

0 commit comments

Comments
 (0)