I am creating a kanban like scrum board. I want to add users to said board. I get the id of board from url then I want to pass on id of user. I have managed to avoid duplicates but there is no respone on return. In django debug tool I get HTTP 201 Created on every request even though the duplicates are not being created in database
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)
It appears that your CreateBoardUserView has the right idea for checking duplicates and permissions, but the Response objects you're returning from within the perform_create method are likely not working as intended. The perform_create method in Django Rest Framework (DRF) doesn't expect a Response object to be returned; instead, it expects you to perform the saving operation or raise an exception that DRF can catch and handle.
To fix your issue, you should raise ValidationError instead of returning Response objects. The DRF framework will catch these exceptions and automatically convert them into the appropriate HTTP responses.
Here's a corrected version of your perform_create method:
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.
Note that:
We raise a PermissionDenied exception when the current user is not the owner. We raise a ValidationError exception when the user is already assigned to the board. We rely on the serializer's is_valid() method to check for user existence and any other validation rules. The actual saving of the instance (via serializer.save()) is done after all checks pass. DRF will handle the exception and return the appropriate response. By raising exceptions instead of returning Response objects within perform_create, DRF's framework will automatically handle the exception and generate a suitable HTTP response to return to the client. This should solve the problem you're experiencing with the HTTP 201 Created status code being returned for every request.