Open
Description
I ran into an issue with a model I was trying to bulk patch that also has a unique_together constraint. Traceback is below. The issue here is that the UniqueTogetherValidator expects to be called from a serializer with a single related instance (i.e. a normal update serializer). But the serializer is in fact instantiated with a queryset.
TBH I don't entirely understand why serializer.instance
is being set to a queryset. But anyway.
Traceback (most recent call last):
File ".../django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File ".../django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File ".../django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File ".../rest_framework/viewsets.py", line 87, in view
return self.dispatch(request, *args, **kwargs)
File ".../rest_framework/views.py", line 466, in dispatch
response = self.handle_exception(exc)
File ".../rest_framework/views.py", line 463, in dispatch
response = handler(request, *args, **kwargs)
File ".../rest_framework_bulk/drf3/mixins.py", line 79, in partial_bulk_update
return self.bulk_update(request, *args, **kwargs)
File ".../rest_framework_bulk/drf3/mixins.py", line 73, in bulk_update
serializer.is_valid(raise_exception=True)
File ".../rest_framework/serializers.py", line 213, in is_valid
self._validated_data = self.run_validation(self.initial_data)
File ".../rest_framework/serializers.py", line 557, in run_validation
value = self.to_internal_value(data)
File ".../rest_framework/serializers.py", line 593, in to_internal_value
validated = self.child.run_validation(item)
File ".../rest_framework/serializers.py", line 409, in run_validation
self.run_validators(value)
File ".../rest_framework/fields.py", line 498, in run_validators
validator(value)
File ".../rest_framework/validators.py", line 142, in __call__
queryset = self.exclude_current_instance(attrs, queryset)
File ".../rest_framework/validators.py", line 135, in exclude_current_instance
return queryset.exclude(pk=self.instance.pk)
AttributeError: 'QuerySet' object has no attribute 'pk'
My workaround was to take advantage of the 'id' attribute that the bulk serializer keeps track of and write a custom unique_together validator.
# validators.py
from rest_framework.validators import UniqueTogetherValidator
class BulkUniqueTogetherValidator(UniqueTogetherValidator):
def exclude_current_instance(self, attrs, queryset):
if attrs.get('id'):
return queryset.exclude(pk=attrs['id'])
return queryset
# serializers.py
from .validators import BulkUniqueTogetherValidator
class ThingSerializer(serializers.HyperlinkedModelSerializer):
<...properties>
def get_unique_together_validators(self):
return [BulkUniqueTogetherValidator(
queryset=Thing.objects.all(),
fields=('field1', 'field2'),
)]
Metadata
Metadata
Assignees
Labels
No labels