My team has run into a bug in UniqueTogetherValidator where it does not work properly with fields with the source attribute. If a field has a source that is different than the field's name on the serializer, then that field is effectively ignored when checking for uniqueness violations, and the ValidationError is not raised.
I am using a serializer set up like this. Note that UniqueTogetherValidator is expecting the serializer's name for the fields argument— you'll get an error on this line if you try to provide the source name instead.
class ExampleSerializer(serializers.Serializer):
list_id = serializers.PrimaryKeyRelatedField(source='list')
position = serializers.IntegerField(source='ordering_key')
class Meta:
validators = [
UniqueTogetherValidator(
queryset=ToDoItem.objects.all(),
fields=['list_id', 'position']
)
]
I believe the bug occurs at this position in the code:
|
else: |
|
# Ignore validation if all field values are unchanged |
|
checked_values = [ |
|
value |
|
for field, value in attrs.items() |
|
if field in self.fields and value != getattr(serializer.instance, field) |
|
] |
|
|
|
if checked_values and None not in checked_values and qs_exists(queryset): |
|
field_names = ', '.join(self.fields) |
|
message = self.message.format(field_names=field_names) |
|
raise ValidationError(message, code='unique') |
On line 172, we check if field (which comes from source) is in self.fields (which is the name on the serializer). If we're looking at the serializer above, then attrs.keys() would be ['list', 'ordering_key'] and self.fields is ['list_id', 'position'].
This means that checked_values will always be empty, and a ValidationError will never be raised.
Checklist
REST Framework version: 3.15.1
My team has run into a bug in
UniqueTogetherValidatorwhere it does not work properly with fields with thesourceattribute. If a field has asourcethat is different than the field's name on the serializer, then that field is effectively ignored when checking for uniqueness violations, and theValidationErroris not raised.I am using a serializer set up like this. Note that
UniqueTogetherValidatoris expecting the serializer's name for thefieldsargument— you'll get an error on this line if you try to provide thesourcename instead.I believe the bug occurs at this position in the code:
django-rest-framework/rest_framework/validators.py
Lines 167 to 178 in e13688f
On line 172, we check if
field(which comes fromsource) is inself.fields(which is the name on the serializer). If we're looking at the serializer above, thenattrs.keys()would be['list', 'ordering_key']andself.fieldsis['list_id', 'position'].This means that
checked_valueswill always be empty, and aValidationErrorwill never be raised.Checklist
REST Framework version: 3.15.1