Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions rest_framework/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,18 @@ def exclude_current_instance(self, attrs, queryset, instance):
return queryset

def __call__(self, attrs, serializer):
if (
serializer.instance is not None and
getattr(serializer.parent, 'many', False) and
not hasattr(serializer.instance, 'pk')
):
raise RuntimeError(
'`UniqueTogetherValidator` cannot determine the current '
'instance during a multiple update. Override '
'`ListSerializer.run_child_validation()` to set '
'`child.instance` before validation.'
)

self.enforce_required_fields(attrs, serializer)
queryset = self.queryset
queryset = self.filter_queryset(attrs, queryset, serializer)
Expand Down
30 changes: 30 additions & 0 deletions tests/test_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,36 @@ def test_updated_instance_excluded_from_unique_together(self):
'position': 1
}

def test_many_update_requires_child_instance(self):
class ListUpdateSerializer(serializers.ListSerializer):
def update(self, instance, validated_data):
return instance

class Serializer(UniquenessTogetherSerializer):
id = serializers.IntegerField()

class Meta(UniquenessTogetherSerializer.Meta):
list_serializer_class = ListUpdateSerializer

serializer = Serializer(
instance=UniquenessTogetherModel.objects.all(),
data=[{
'id': self.instance.pk,
'race_name': self.instance.race_name,
'position': self.instance.position,
}],
many=True,
)
message = (
'`UniqueTogetherValidator` cannot determine the current instance '
'during a multiple update. Override '
'`ListSerializer.run_child_validation()` to set `child.instance` '
'before validation.'
)

with pytest.raises(RuntimeError, match=re.escape(message)):
serializer.is_valid()

def test_unique_together_is_required(self):
"""
In a unique together validation, all fields are required.
Expand Down
Loading