【问题标题】:Django-REST: Get User by username instead of primary-keyDjango-REST:通过用户名而不是主键获取用户
【发布时间】:2015-11-15 13:47:44
【问题描述】:

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

我添加了一个新的详细路由,但是当我尝试使用 URL /api/users/retrieve_by_username/altoyr 获取用户时,我总是在我的服务器上得到 404

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'))
]

我认为我缺少构建休息网址的重要部分。

【问题讨论】:

标签: python django-rest-framework


【解决方案1】:

您可以通过添加如下列表路由来做到这一点:

@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

【讨论】:

  • 这看起来不错,在阅读了一些关于 REST-Urls 的内容后,我认为 Url 应该看起来像 /api/users/username/altoyr。我在家的时候试试你的方法。
【解决方案2】:

您可以覆盖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)

【讨论】:

    【解决方案3】:

    Anush Devendra 的答案是正确的,但由于v3.9 已被弃用,因此需要进行一些更新。

    action 装饰器替换 list_routedetail_route list_routedetail_route 现在都被弃用了,取而代之的是单动作装饰器。它们将在 3.10 中完全删除。 动作装饰器采用布尔详细参数。

    • 将 detail_route 使用替换为 @action(detail=True)。
    • 将 list_route 使用替换为 @action(detail=False)。
    ...
    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。如果你没有它,你可能不需要它。

    【讨论】:

      猜你喜欢
      • 2019-09-27
      • 1970-01-01
      • 2022-06-14
      • 2017-12-06
      • 2016-08-10
      • 2015-02-24
      • 2020-10-03
      • 2018-02-21
      • 1970-01-01
      相关资源
      最近更新 更多