I was wondering, I have the following within the Meta class of a model:
class Meta:
unique_together = ['owner', 'question', 'answer']
Within my API viewset, I perform the create as the following:
def create(self, request, *args, **kwargs):
serializer = self.get_serializer_class()(data=request.data, context={'request': request,}, many=False)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
Which is very formulaic Django REST Framework thus far.
The serializer is as follows:
class SurveyResultCreateOrUpdateSerializer(serializers.ModelSerializer):
owner = serializers.PrimaryKeyRelatedField(
read_only=True,
default=serializers.CurrentUserDefault()
)
class Meta:
model = SurveyResult
fields = [
'uuid', 'id', 'question', 'answer', 'owner',
]
read_only_fields = [
'uuid', 'id', 'owner',
]
validators = [
UniqueTogetherValidator(
queryset=SurveyResult.objects.all(),
fields=['owner', 'question', 'answer']
)
]
So, when trying to create if an object where the validation fails, the error is raised. Brillaint. This is expected behaviour.
However, when the error is raised, I would like to immediately perform an update attempt if the unique together validation has been thrown...?
What would be the "pattern" way of doing this? Should I knock the serializer.is_valid() method to an if else statement, and on the else...or can I catch the raised exception only if the exception is a unique together error? Should I perform a separate update call from the client dependent on the response? Is there a way of creating an "perform_create_or_update()" function within the viewset? Is there a create_or_update viewset method?
My starting point would be something like this:
def create(self, request, *args, **kwargs):
serializer = self.get_serializer_class()(data=request.data, context={'request': request,}, many=False)
try:
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
except exceptions.ValidationError as error:
if 'unique' in error.get_codes()['non_field_errors'] and len(error.get_codes()['non_field_errors']) == 1:
print("We should try and update")
return Response(