首页 > 解决方案 > 按用户名格式化url

问题描述

我有一个用 DRF 构建的小型消息 API,它在系统中的用户之间发送消息。我的消息视图包含几个额外的操作:

class MessagesViewSet(ModelViewSet):
    """
    A simple ViewSet for viewing and editing the messages
    associated with the user.
    """
    authentication_classes = [TokenAuthentication, ]
    permission_classes = [IsAuthenticated]
    serializer_class = MessageSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_fields = [MessageFields.MARK_READ]

    def get_user(self):
        user = self.request.user
        return user

    def get_queryset(self):
        return Message.objects.filter(sent_to=self.get_user())

    @action(detail=True)
    def sent_messages(self, request, pk):
        """
        Return all messages sent by the user.
        """
        queryset = Message.objects.filter(sender=self.get_user())
        serialized_data = MessageSerializer(queryset, many=True)
        return Response(serialized_data.data, status=HTTP_200_OK)

    @action(detail=True)
    def last_50_messages(self, request, pk):
        """
        Return the user's 50 last messages
        """
        queryset = Message.objects.filter(sent_to=self.get_user())
        serialized_data = MessageSerializer(queryset, many=True)
        return Response(serialized_data.data, status=HTTP_200_OK)

网址文件:

from .views import MessagesViewSet

messages_router = DefaultRouter()
messages_router.register(r'messages', MessagesViewSet, basename='messages')

urlpatterns = [
    url('', include(messages_router.urls))
]

现在,访问这两个自定义方法的唯一方法是打开其中一个消息实例,然后将其添加到 URL 行,它就会起作用。

如何格式化每种方法的 url,使其通过用户名?马上:

http://127.0.0.1:8000/api/messages/1/sent_messages/

我正在寻找类似的东西:

http://127.0.0.1:8000/api/messages/#request.user.username/sent_messages/

标签: pythondjangodjango-rest-frameworkdjango-urls

解决方案


您必须像这样更改 lookup_fieldModelViewSet

class MessagesViewSet(ModelViewSet):
    ...
    lookup_field = "username"
    ...

但要小心,类似 API 的 APIretrieve也可以用于username查找,而不是pk. 要在此处
同时使用(用户名、查找)检查挂钩:

class MultipleFieldLookupORMixin(object):
    """
    Actual code http://www.django-rest-framework.org/api-guide/generic-views/#creating-custom-mixins
    Apply this mixin to any view or viewset to get multiple field filtering
    based on a `lookup_fields` attribute, instead of the default single field filtering.
    """
    def get_object(self):
        queryset = self.get_queryset()             # Get the base queryset
        queryset = self.filter_queryset(queryset)  # Apply any filter backends
        filter = {}
        for field in self.lookup_fields:
            try:                                  # Get the result with one or more fields.
                filter[field] = self.kwargs[field]
            except Exception:
                pass
        return get_object_or_404(queryset, **filter)  # Lookup the object

class RetrieveUserView(MultipleFieldLookupORMixin, generics.RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    lookup_fields = ('account', 'username')

推荐阅读