【问题标题】:Django Rest Framework unique together validation with field absent from requestDjango Rest Framework 唯一的验证与请求中缺少的字段
【发布时间】:2020-08-14 05:37:37
【问题描述】:

我正在一个应用程序中实现一些投票功能,其中登录用户指定一个他们想要投票的帖子,使用这样的有效负载:

{
  "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 强制执行唯一的共同验证,两个字段(在我的情况下为 userpost)必须包含在序列化程序的 fields 中。正如我所提到的,我想避免这种情况。有没有其他方法可以实现这种类型的验证逻辑?

编辑:

澄清:记录不保存 - 我收到此错误:

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 序列化程序并从有效负载中排除所需字段时所做的那样。

【问题讨论】:

  • 无法复制。你用的是什么rest-framework 版本?
  • @drec4s 3.11.0 - 你能描述一下你看到的行为吗?
  • 我也在使用 3.11 版,并获得了IntegrityError: UNIQUE constraint failed: vote.post_id, vote.user_id
  • @drec4s 为了清楚起见,我更新了我的帖子。我的目标是优雅地处理这些错误,而不是向客户端返回 500。

标签: django django-rest-framework


【解决方案1】:

要输出由于IntegrityError 而导致的自定义错误消息,您可以在序列化程序中覆盖create 方法:

from django.db import IntegrityError

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

    def create(self, validated_data):
        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)

【讨论】:

    【解决方案2】:

    你可以在你的视图上试试这个

    try:
        MoviesWatchList.objects.create(user=request.user, content=movie)
        return response.Response({'message': f'{movie} added in watchlist.'}, status=status.HTTP_201_CREATED)
    except:
        return response.Response({'message': f'{movie} already added to watchlist.'}, status=status.HTTP_304_NOT_MODIFIED)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-07
      • 1970-01-01
      • 2015-09-25
      • 2021-12-03
      • 2018-05-17
      • 1970-01-01
      • 1970-01-01
      • 2019-11-20
      相关资源
      最近更新 更多