Поиск URL не работает при обновлении и извлечении

В url /users/*username я должен иметь возможность получить доступ к каждому пользователю по его имени пользователя, проблема в том, что это не работает так, как должно, не имеет значения, что я пишу в *username, он будет обновлять/удалять текущего зарегистрированного пользователя.

Пример: Я могу обновить пользователя "admin" через /users/123/, даже если 123 явно не является администратором или любым другим существующим пользователем.

Вот представление пользователя с методами, которые не работают так, как я задумал:

class UserViewSet(mixins.RetrieveModelMixin,
              mixins.UpdateModelMixin,
              mixins.DestroyModelMixin,
              viewsets.GenericViewSet):

serializer_class = UserSerializer
lookup_field = 'username'

queryset = User.objects.all()

def get_permissions(self):
    if self.action in ['signup', 'login',]:
        permissions = [AllowAny]
    elif self.action in ['retrieve', 'update', 'destroy']:
        permissions = [IsAuthenticated, IsSameUser]
    else:
        permissions = [IsAuthenticated]
    return [p() for p in permissions]


def retrieve(self, request, *args, **kwargs):
    response = super(UserViewSet, self).retrieve(request, *args, **kwargs)
    data = response.data
    return Response(data=data, status=status.HTTP_200_OK)

def update(self, request, *args, **kwargs):
    serializer = UserModelSerializer(request.user, data=request.data, partial=True)
    serializer.is_valid(raise_exception=True)
    serializer.save()
    return Response(serializer.data, status=status.HTTP_200_OK)

будет обновлять/удалять текущего зарегистрированного пользователя.

Конечно

Ваш метод обновления:

def update(self, request, *args, **kwargs):
    serializer = UserModelSerializer(request.user, data=request.data, partial=True)
    serializer.is_valid(raise_exception=True)
    serializer.save()
    return Response(serializer.data, status=status.HTTP_200_OK)

где request.user - вошедший в систему пользователь.


Правильный код выглядит примерно так:

class UserViewSet(mixins.RetrieveModelMixin,
                  mixins.UpdateModelMixin,
                  mixins.DestroyModelMixin,
                  viewsets.GenericViewSet):

    serializer_class = UserSerializer
    lookup_field = 'username'

    queryset = User.objects.all()

    ...
    
    def update(self, url_username, request, *args, **kwargs):
        try:
            user_object = self.queryset.get(username=url_username)
        except User.DoesNotExist:
             Response({'error': 'not found'}, status=404)
        serializer = UserModelSerializer(user_object, data=request.data, partial=True)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_200_OK)

Также вам нужно добавить url_username в URL путь:

urlpatterns = [
    ...,
    path('users/<str:url_username>', update_user)
]

Здесь

  • user_object - пользователь, которого вы хотите обновить
  • request.data - это новые данные, которые вы хотите установить для существующего пользователя
  • url_username - это *username часть в /users/*username для получения точного пользователя

в вашем сериализаторе UserSerializer необходимо добавить этот мета-класс:

    class Meta:
        lookup_field = 'username'
Вернуться на верх