Serializer `UniqueConstraint` validation fails incorrectly on create with conditional fields
Issue:
Adding the following test to TestUniqueConstraintValidation demonstrates an issue in the serializer’s unique constraint validation logic:
def test_unique_constraint_create(self):
class SourceUniqueConstraintSerializer(serializers.ModelSerializer):
raceName = serializers.CharField(source="race_name")
class Meta:
model = UniqueConstraintModel
fields = ("raceName", "position", "global_id", "fancy_conditions")
UniqueConstraintModel.objects.exclude(pk=self.instance.pk).delete()
data = {
"race_name": "other",
"position": 1,
"global_id": 3,
"fancy_conditions": 1,
}
obj = UniqueConstraintModel.objects.create(**data)
obj.delete()
serializer = SourceUniqueConstraintSerializer(data=data)
assert serializer.is_valid() # This unexpectedly fails
- Creating a UniqueConstraintModel instance directly with UniqueConstraintModel.objects.create() succeeds, indicating no unique constraint violation occurs at the database level.
- However, validating the same data through the ModelSerializer fails.
Root cause:
The unique validator used by the serializer does not account for the global_id field during validation of fancy_conditions, even though global_id is part of the conditional logic in the unique constraint.
As a result, the validation incorrectly identifies a conflict based only on fancy_conditions, without considering that the global_id in the input data should exempt it from the constraint.
Expected behavior:
Serializer validation should succeed in this case, consistent with the model-level behavior.
can you check this PR please https://github.com/encode/django-rest-framework/pull/9712 ?
@auvipy this unfortunately doesn't resolve the issue. I think the failure happens in the unique validator call since does not consider the fields included in constraint conditions.
https://github.com/kalekseev/django-rest-framework/blob/f30c0e2eedda410a7e6a0d1b351377a9084361b4/rest_framework/validators.py#L66
Do you have the capacity to fix this?
@auvipy I might have some time in the next few weeks to take a look.
@auvipy tentative fix now up here: https://github.com/encode/django-rest-framework/pull/9744.
@nefrob @auvipy Do you intend to continue working on this?
@Adiorz just looking for desired direction. If we want something more comprehensive / specific than the above PR, I probably won't have time and would defer to someone else. I can make a few small adjustments on the existing approach if needed however.