未收到关于检测重复项的回应
我正在创建一个类似于看板的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 个回答
看起来你的 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 状态码的问题。