@action получил неожиданный аргумент ключевого слова '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')
Ошибка типа: функция set_or_delete_subscribe() получила неожиданный аргумент ключевого слова 'id' [10/Март/2025 08:38:23] "ОПУБЛИКОВАТЬ /api/пользователи/11/подписаться/ HTTP/1.0" 500 88724
Я не могу понять, почему get_object() ожидает идентификатор и не принимает pk ? Возможно, я что-то упускаю, но не могу уловить это. Мне нужно подписаться на пользователя или удалить его, если он уже подписан.
Наборы просмотра DRF с параметром detail=True используют pk, а не id. Вам следует изменить:
user_to_subscribe = get_object_or_404(User, pk=pk)
Правильный код:
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)`
изменение :
user_to_subscribe = self.kwargs['id']
чтобы :
user_to_subscribe = self.kwargs['pk']
Ваш urls.py
регистрируется CustomUserViewSet
под users
, поэтому URL /api/users/11/subscribe/
должен соответствовать 11
как pk
, а не id
. Обратите внимание, что Действия ViewSet всегда получают pk
в качестве идентификатора.