未收到关于检测重复项的回应

0 投票
1 回答
24 浏览
提问于 2025-04-14 17:22

我正在创建一个类似于看板的Scrum板。我想把用户添加到这个板上。我从网址中获取了板的ID,然后想传递用户的ID。我已经成功避免了重复添加,但返回时没有任何响应。在Django的调试工具中,我每次请求都会看到HTTP 201 Created,尽管数据库中并没有创建重复项。

models.py

class Board(models.Model):
    name = models.CharField(max_length=250)
    description = models.TextField()
    create_date = models.DateField(auto_now=True)
    due_date = models.DateField()

    def __str__(self):
        return self.name

class BoardUser(models.Model):
    board = models.ForeignKey(Board, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    is_owner = models.BooleanField(default=False)

serializer.py

class BoardUserSerializer(serializers.ModelSerializer):
    #board = BoardSerializer(read_only=True)
    #user = UserSerializer(read_only=True)
    is_owner = serializers.BooleanField(read_only=True)


    class Meta:
        model = models.BoardUser
        fields = (
            'board',
            'user',
            'is_owner',
        )

views.py

class CreateBoardUserView(generics.CreateAPIView):
    queryset = BoardUser.objects.all()
    serializer_class = BoardUserSerializer
    permission_classes = [permissions.IsAuthenticated]

    def perform_create(self, serializer):
        # Extract board ID from URL
        board_id = self.kwargs.get('board_id')

        # Get the authenticated user
        user = self.request.user

        # Get the user ID from the request data
        user_id = self.request.data.get('user')

        # Retrieve the board instance directly from the database
        board_instance = Board.objects.get(pk=board_id)

        try:
            # Convert user ID to User instance
            user_instance = User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return Response({'message': 'Invalid user ID provided.'}, status=status.HTTP_400_BAD_REQUEST)

        # Check if the user is the owner of the board
        board_user = BoardUser.objects.filter(board=board_instance, user=user).first()
        if not board_user or not board_user.is_owner:
            return Response({'message': 'You are not the owner of this board.'}, status=status.HTTP_403_FORBIDDEN)

        # Check if the user is already assigned to this board
        if BoardUser.objects.filter(board=board_instance, user=user_instance).exists():
            return Response({'message': 'User is already assigned to this board.'}, status=status.HTTP_400_BAD_REQUEST)

        # Avoid duplicates
        try:
            serializer.save(board=board_instance, user=user_instance)
            return Response({'message': 'Board user created successfully.'}, status=status.HTTP_201_CREATED)
        except Exception as e:
            return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

1 个回答

-1

看起来你的 CreateBoardUserView 在检查重复和权限方面思路是对的,但在 perform_create 方法中返回的 Response 对象可能没有按预期工作。在 Django Rest Framework (DRF) 中,perform_create 方法并不期望返回一个 Response 对象;相反,它希望你执行保存操作,或者抛出一个 DRF 可以捕获和处理的异常。

要解决这个问题,你应该抛出 ValidationError,而不是返回 Response 对象。DRF 框架会捕获这些异常,并自动将它们转换成合适的 HTTP 响应。

这是你 perform_create 方法的一个修正版本:

from rest_framework.exceptions import ValidationError, PermissionDenied
from rest_framework.response import Response
from rest_framework import status

# Other imports ...

class CreateBoardUserView(generics.CreateAPIView):
    # ... your existing code ...

    def perform_create(self, serializer):
        board_id = self.kwargs.get('board_id')
        user = self.request.user
        user_id = self.request.data.get('user')

        board_instance = Board.objects.get(pk=board_id)

        # Check for user existence and handle User.DoesNotExist within the serializer
        serializer.is_valid(raise_exception=True)
        user_instance = serializer.validated_data['user']

        # Check if the user is the owner of the board
        board_user = BoardUser.objects.filter(board=board_instance, user=user).first()
        if not board_user or not board_user.is_owner:
            raise PermissionDenied({'message': 'You are not the owner of this board.'})

        # Check if the user is already assigned to this board
        if BoardUser.objects.filter(board=board_instance, user=user_instance).exists():
            raise ValidationError({'message': 'User is already assigned to this board.'})

        # No exceptions raised: save the instance
        serializer.save(board=board_instance, user=user_instance)

        # The response will be handled by DRF, no need to return it here.

注意:

当当前用户不是拥有者时,我们抛出 PermissionDenied 异常。
当用户已经被分配到这个板块时,我们抛出 ValidationError 异常。
我们依赖序列化器的 is_valid() 方法来检查用户是否存在以及其他验证规则。
在所有检查通过后,实际的实例保存(通过 serializer.save())才会进行。
DRF 会处理这个异常并返回合适的响应。

通过在 perform_create 中抛出异常,而不是返回 Response 对象,DRF 框架会自动处理这个异常,并生成一个合适的 HTTP 响应返回给客户端。这应该能解决你在每个请求中都返回 HTTP 201 Created 状态码的问题。

撰写回答