'One review per user in the current title

I am trying to make so that every user could only post one review per title (product). First idea was to do this through UniqueTogether, but it resulted unsuccessful. So now, I thought to complete it by validate in serializer.

Right now I am getting the following error: TypeError: Review() got an unexpected keyword argument 'title'. But if you look at my code below I did not pass title argument to Review(). I even tried to make error on purpose to see what arguments I can pass to Review() and title was not there.

django.core.exceptions.FieldError: Cannot resolve keyword 'title_d' into field. Choices are: author, 
author_id, comments, id, pub_date, score, text, title_id, title_id_id

serializers.py

class ReviewSerializer(serializers.ModelSerializer):
    author = serializers.SlugRelatedField(
        slug_field='username',
        default=serializers.CurrentUserDefault(),
        read_only=True
    )

    class Meta:
        model = Review
        fields = ('id', 'text', 'author', 'score', 'pub_date')

    def validate(self, data):
        title_id = self.context['view'].kwargs['title_id']
        author = self.context['request'].user
        if Review.objects.filter(title_id=title_id, author=author).exists():
            raise serializers.ValidationError(
                'You cannot post second review on same item.'
            )
        return data

models.py

class Review(models.Model):
    title_id = models.ForeignKey(
        Title,
        on_delete=models.DO_NOTHING,
        related_name='reviews'
    )
    text = models.TextField(
        'Текст отзыва'
    )
    author = models.ForeignKey(
        User,
        on_delete=models.DO_NOTHING,
        verbose_name='Автор',
        related_name='reviews'
    )
    score = models.IntegerField(
        choices=SCORES
    )
    pub_date = models.DateTimeField(
        'Дата публикации',
        auto_now_add=True,)



class Title(models.Model):
    name = models.CharField(
        max_length=255,
        verbose_name='Название произведения'
    )

    year = models.IntegerField(
        verbose_name='Год произведения'
    )

    category = models.ForeignKey(
        Category,
        on_delete=models.DO_NOTHING,
        verbose_name='Категория произведения',
        related_name='category_title',
    )

    description = models.TextField(
        verbose_name='Описания произведения',
        blank=True,
        null=True
    )

    rating = models.IntegerField(
        verbose_name='Рейтинг произведения',
        blank=True,
        null=True
    )

    genres = models.ManyToManyField(
        Genre,
        through='GenreTitle',
    )

views.py

class ReviewViewSet(viewsets.ModelViewSet):
    serializer_class = ReviewSerializer
    pagination_class = LimitOffsetPagination
    permission_classes = [ReviewAndComment, IsAuthenticatedOrReadOnly]

    def get_queryset(self):
        title = get_object_or_404(Title, id=self.kwargs['title_id'])
        return title.reviews.all()

    def perform_create(self, serializer):
        title = get_object_or_404(Title,
                                  id=self.kwargs['title_id'])
        author = get_object_or_404(User,
                                   username=self.request.user)
        reviews = Review.objects.filter(title=title.pk)
        scores = reviews.values_list('score', flat=True)
        scores = list(scores)
        scores.append(serializer.validated_data['score'])
        rating = sum(scores) / len(scores)
        title.rating = round(rating)
        title.save()
        serializer.save(title=title,
                        author=author)


Solution 1:[1]

Change name of title_id field into 'title'. Also in validation do one change:

def validate(self, data):
    title = int(data['title'])
    author = self.context['request'].user   # here maybe self.request.user might work too
    if Review.objects.filter(title=title, author=author).exists():
    ...

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 NixonSparrow