简体   繁体   English

Django-REST:通过用户名而不是主键获取用户

[英]Django-REST: Get User by username instead of primary-key

I am using the basic UserViewSet derived from ModelViewSet.我正在使用从 ModelViewSet 派生的基本 UserViewSet。
Retrieving a user with a primary-key via api/users/<pk> works fine.通过api/users/<pk>使用主键检索用户工作正常。
But I also want to be able to retrieve a User by Username.但我也希望能够通过用户名检索用户。

I have added a new detail route but I always get 404 on my server when I try to get the user with the url /api/users/retrieve_by_username/altoyr .我添加了一个新的详细路由,但是当我尝试使用 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)

The Urls are registered via a router:网址是通过路由器注册的:

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

I think I am missing an important part of building rest urls.我想我错过了构建休息网址的重要部分。

You can do this by adding a list route like:您可以通过添加一个列表路由来做到这一点,如:

@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)

and the url will be like:网址将如下所示:

/api/users/retrieve_by_username/altoyr

You can override the retrieve() ViewSet action.您可以覆盖retrieve() ViewSet 操作。 You'll find more detail here: https://www.django-rest-framework.org/api-guide/viewsets/您可以在此处找到更多详细信息: 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)

The answer from Anush Devendra is right but need a little update due to deprecations on v3.9 . Anush Devendra的答案是正确的,但由于v3.9 的弃用需要进行一些更新。

action decorator replaces list_route and detail_route Both list_route and detail_route are now deprecated in favour of the single action decorator. action 装饰器替换list_routedetail_route现在不推荐使用list_routedetail_route以支持单个动作装饰器。 They will be removed entirely in 3.10.它们将在 3.10 中完全删除。 The action decorator takes a boolean detail argument.动作装饰器接受一个布尔细节参数。

  • Replace detail_route uses with @action(detail=True).用@action(detail=True) 替换 detail_route 使用。
  • Replace list_route uses with @action(detail=False).用@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)

I add context={'request': request} because I have url as HyperlinkedIdentityField in my serializer.我添加context={'request': request}因为我的序列化程序中有url作为 HyperlinkedIdentityField 。 If you don't have it, you probably don't need it.如果你没有它,你可能不需要它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM