检测到重复项时没有得到响应

问题描述 投票:0回答:1

我正在创建一个类似看板的 Scrum 板。我想将用户添加到所述板上。我从 url 获取板的 id,然后我想传递用户的 id。我已设法避免重复,但返回后没有任何回复。在 django 调试工具中,即使没有在数据库中创建重复项,我也会在每个请求上收到 HTTP 201 Created

模型.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)

序列化器.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)
python django-rest-framework django-views
1个回答
0
投票

您的 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 状态代码的问题。

© www.soinside.com 2019 - 2024. All rights reserved.