Zoli
Zoli

Reputation: 836

Validate serializer object without the field need for validation

I have a following viewset,

class VoteViewSet(viewsets.ModelViewSet):
    serializer_class = VoteSerializer
    permission_classes = [IsAuthenticated]

    def perform_create(self, serializer):
        serializer.save(created_by=self.request.user)

    def get_queryset(self):
        return Vote.objects.filter(created_by=self.request.user)

serializer

class VoteSerializer(serializers.ModelSerializer):
    class Meta:
        model = Vote
        fields = ('id', 'request')
        read_only_fields = ('id',)

and model.

class Vote(models.Model):
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='votes')
    request = models.ForeignKey(Request, related_name='votes')

    class Meta:
        unique_together = [('request', 'created_by')]

I am trying to save user's vote but I get IntegrityError: UNIQUE constraint failed when I post a vote for the same request twice. I can fix the error by adding created_by to VoteSerializer however I don't want to have it in my serialized data. What are my options?

Upvotes: 0

Views: 1861

Answers (2)

user8060120
user8060120

Reputation:

you can try object-level-validation

class VoteSerializer(serializers.ModelSerializer):
    class Meta:
        model = Vote
        fields = ('id', 'request')
        read_only_fields = ('id',)

    def validate(self, data):
        """
        Check Unique vote per user.
        """
        created_by = self.context['request'].user
        if self.instance is None:
            Vote(**data, created_by=created_by).full_clean()
        else:
            self.instance.created_by = created_by
            self.instance.full_clean()
        return data

Upvotes: 2

KyleDing
KyleDing

Reputation: 118

from rest_framework.validators import UniqueTogetherValidator

class ExampleSerializer(serializers.Serializer):
    # ...
    class Meta:
        # ToDo items belong to a parent list, and have an ordering defined
        # by the 'position' field. No two items in a given list may share
        # the same position.
        validators = [
            UniqueTogetherValidator(
                queryset=ToDoItem.objects.all(),
                fields=('list', 'position')
            )
        ]

UniqueTogetherValidator

Upvotes: 1

Related Questions