Django Проверка уникальной общей структуры Rest Framework с полем, отсутствующим в запросе - PullRequest
1 голос
/ 30 апреля 2020

Я реализую некоторые функции голосования в приложении, где зарегистрированный пользователь указывает сообщение, за которое он хотел бы проголосовать за использование полезной нагрузки, например:

{
  "post": 1,
  "value": 1
}

Как вы можете сказать, поле user отсутствует - это потому, что оно установлено в методе perform_create моего набора. Я сделал это, чтобы убедиться, что голосование user установлено на стороне сервера. Вот как выглядит набор:

class CreateVoteView(generics.CreateAPIView):
    permission_classes = (permissions.IsAuthenticated,)
    serializer_class = VoteSerializer

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

Вот как выглядит модель:

class Vote(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='votes', null=False)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='votes', null=False)

    class Values(models.IntegerChoices):
        UP = 1, _('Up')
        DOWN = -1, _('Down')

    value = models.IntegerField(choices=Values.choices, null=False)

    class Meta:
        unique_together = ('post', 'user')

и, наконец, сериализатор:

class VoteSerializer(serializers.ModelSerializer):
    class Meta:
        model = Vote
        fields = ['post', 'value']

От Насколько я понимаю, для того, чтобы DRF обеспечивал уникальную совместную проверку, оба поля (в моем случае user и post) должны быть включены в сериализатор fields. Как я уже говорил, я бы хотел этого избежать. Есть ли другой способ реализации этого типа проверки логи c?

РЕДАКТИРОВАТЬ:

Чтобы уточнить: записи не сохраняются - я получаю эту ошибку:

django.db.utils.IntegrityError: (1062, "Duplicate entry '1-3' for key 'api_vote.api_vote_post_id_user_id_73614533_uniq'")

Тем не менее, моя цель - вернуть Bad Request вместо Internal Server Error так же, как я это делал, когда традиционно использовал сериализатор DRF и исключал обязательные поля из полезной нагрузки.

1 Ответ

0 голосов
/ 30 апреля 2020

Чтобы вывести пользовательское сообщение об ошибке из-за IntegrityError, вы можете переопределить метод create в вашем сериализаторе:

<b>from django.db import IntegrityError</b>

class VoteSerializer(serializers.ModelSerializer):
    class Meta:
        model = Vote
        fields = ['post', 'value']

    def create(self, validated_data):
        <b>try:
            validated_data['user'] = self.context['request'].user
            return super().create(validated_data)
        except IntegrityError:
            error_msg = {'error': 'IntegrityError message'}
            raise serializers.ValidationError(error_msg)</b>
...