@action got an unexpected keyword argument 'id'

class CustomUserViewSet(UserViewSet):
    
    serializer_class = UserSerializer
    pagination_class = PageNumberPagination
    permission_classes = [permissions.IsAuthenticated]
    
    def get_queryset(self):
        queryset = User.objects.all()
        return queryset
    
    @action(detail=False, methods=['put', 'delete'], url_path='me/avatar')
    def set_avatar(self, request):
        if request.method == 'PUT':
            serializer = SetAvatarSerializer(
                request.user,
                data=request.data,
                partial=True
            )
            serializer.is_valid(raise_exception=True)
            serializer.save()
            return Response(status=status.HTTP_200_OK)
        user = request.user
        user.avatar.delete()
        user.save()
        return Response(status=status.HTTP_204_NO_CONTENT)
    
    @action(detail=True, methods=['post', 'delete'], url_path='subscribe')
    def set_or_delete_subscribe(self, request, pk=None):
        user = request.user
        user_to_subscribe = self.kwargs['id']
        if request.method == 'POST':
            _, created = Subscription.objects.get_or_create(user=user, subscribed=user_to_subscribe)
            if created:
                return Response(status=status.HTTP_201_CREATED)
            return Response(status=status.HTTP_400_BAD_REQUEST)

        if request.method == 'DELETE':
            subscription = Subscription.objects.filter(user=user, subscribed=user_to_subscribe).delete()
            if subscription:
                return Response(status=status.HTTP_204_NO_CONTENT)
            return Response(status=status.HTTP_400_BAD_REQUEST)


model of Subscription

class Subscription(models.Model):
    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='subscriptions'
    )
    subscribed = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='subscribed'
    )

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=['user', 'subscribed'], name='unique_subscription')
        ]

urls

router = DefaultRouter()
router.register(r'tags', TagViewSet, basename='tags')
router.register(r'recipes', RecipeViewSet, basename='recipes')
router.register(r'ingredients', IngridientsViewSet, basename='ingredients')
router.register(r'users', CustomUserViewSet, basename='users')

TypeError: set_or_delete_subscribe() got an unexpected keyword argument 'id' [10/Mar/2025 08:38:23] "POST /api/users/11/subscribe/ HTTP/1.0" 500 88724

I can't figure out why get_object() expects id and doesn't accept pk ? Ьaybe I'm missing something, but I can't catch it. I need to subscribe to a user or delete them if already subscribed.

DRF ViewSets with detail=True use pk, not id. You should to change:

user_to_subscribe = get_object_or_404(User, pk=pk)

Correct code:

def set_or_delete_subscribe(self, request, pk=None):
    user = request.user
    user_to_subscribe = get_object_or_404(User, pk=pk)

    if request.method == 'POST':
        _, created = Subscription.objects.get_or_create(user=user, subscribed=user_to_subscribe)
        if created:
            return Response(status=status.HTTP_201_CREATED)
        return Response(status=status.HTTP_400_BAD_REQUEST)

    if request.method == 'DELETE':
        subscription = Subscription.objects.filter(user=user, subscribed=user_to_subscribe).delete()
        if subscription:
            return Response(status=status.HTTP_204_NO_CONTENT)
        return Response(status=status.HTTP_400_BAD_REQUEST)`

Вернуться на верх