Django-REST:按用户名而不是主键

时间:2015-11-15 13:47:45

标签: python django-rest-framework

我正在使用从ModelViewSet派生的基本UserViewSet 通过api/users/<pk>检索具有主键的用户可以正常工作 但我也希望能够通过用户名检索用户。

我添加了一条新的详细信息路线,但当我尝试使用网址404向用户提供时,我总是在我的服务器上获得/api/users/retrieve_by_username/altoyr

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    @detail_route(methods=['get'])
    def retrieve_by_username(self, request, username=None):
        try:
            user = User.objects.get(userName=username)
            return Response(user)
        except User.DoesNotExist:
            return Response("No user with username found!", status=status.HTTP_400_BAD_REQUEST)

网址是通过路由器注册的:

router = DefaultRouter()
router.register(r'users', views.UserViewSet)

# The API URLs are now determined automatically by the router.
# Additionally, we include the login URLs for the browsable API.
urlpatterns = [
    url(r'^', include(router.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

我想我错过了建立休息网址的重要部分。

3 个答案:

答案 0 :(得分:5)

您可以通过添加列表路径来执行此操作,例如:

@list_route(methods=['get'], url_path='retrieve_by_username/(?P<username>\w+)')
def getByUsername(self, request, username ):
    user = get_object_or_404(User, username=username)
    return Response(UserSerializer(user).data, status=status.HTTP_200_OK)

并且网址将如下:

/api/users/retrieve_by_username/altoyr

答案 1 :(得分:0)

您可以覆盖retrieve()ViewSet操作。您将在此处找到更多详细信息:https://www.django-rest-framework.org/api-guide/viewsets/

from django.shortcuts import get_object_or_404
from rest_framework.response import Response

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def retrieve(self, request, pk=None):
        queryset = User.objects.filter(username=pk)
        contact = get_object_or_404(queryset, pk=1)
        serializer = ContactSerializer(contact)
        return Response(serializer.data)

答案 2 :(得分:0)

Anush Devendra的答案是正确的,但由于v3.9的弃用而需要稍作更新。

动作修饰符替换list_routedetail_route list_routedetail_route现在都已弃用,以单个操作装饰器为好。它们将在3.10中完全删除。 动作装饰器采用布尔详细参数。

  • 使用@action(detail = True)替换detail_route使用。
  • 使用@action(detail = False)替换list_route。
...
from rest_framework.decorators import action
from rest_framework.response import Response
from django.shortcuts import get_object_or_404
from rest_framework import status

class UserViewSet(viewsets.ModelViewSet):
    ...

    @action(methods=['get'], detail=False,
            url_path='username/(?P<username>\w+)')
    def getByUsername(self, request, username):
        user = get_object_or_404(User, username=username)
        data = UserSerializer(user, context={'request': request}).data
        return Response(data, status=status.HTTP_200_OK)

我添加context={'request': request}是因为我的序列化程序中有url作为HyperlinkedIdentityField。如果您没有它,则可能不需要。