[Answered ]-Django REST Framework UniqueTogetherValidator fails with FK from kwargs

1👍

def create(self, validated_data):
    try:
        review = Review.objects.create(**validated_data)
    except IntegrityError:
        raise serializers.ValidationError(
            {'detail': 'Вы можете оставить только один отзыв.'})
    return review

Currently fixed like that but seems wrong to me.

0👍

First, I will assume that BasePostViewSet does inherits from CreateModelMixin. My assumption is based on the fact that you are redefining perform_create:

def perform_create(self, serializer):
    serializer.save()

According to DRF Documentation on passing additional argumernts to the .save() method:

Any additional keyword arguments will be included in the validated_data argument when .create() or .update() are called.

The original .create() method from the CreateModelMixin:

def create(self, request, *args, **kwargs):
    serializer = self.get_serializer(data=request.data)
    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)

It does the validation before calling the .perform_create() method, hence your redefined version of .perform_create:

def perform_create(self, serializer):
    serializer.save(author=self.request.user, review=self.get_review())

Gets called after validation, hence, your serializer validator is not checked with your desired arguments.

Now, I think you could achieve this by including your fields in the to_internal_value function data like this (didn’t try it out but definitely it runs before validation) (I’m assuming that serializer context is passed accordingly):

def to_internal_value(self, data):
    data['author'] = self.context['request'].user
    data['review'] = self.context['view'].get_review()
    return data

Hopefully this helps.

Leave a comment