如何在不传递 url 中的主键的情况下向 ModelViewSet 发送 PUT 请求?

How to send PUT request to ModelViewSet without passing a primary key in the url?

我对使用 ModelViewSet 特别感兴趣 用于解决更新登录用户个人资料的挑战。我正在使用以下定义:

from rest_framework import viewsets

class ProfileRetrieveUpdate(viewsets.ModelViewSet):
    serializer_class = UserProfileSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]

    def get_queryset(self):
        return UserProfile.objects.filter(user=self.request.user)

    def perform_update(self, serializer):
        serializer.save(user=self.request.user)

通过覆盖 get_queryset,我能够获得预期的行为,即当我访问端点时(例如 profile/),我获得了登录用户的配置文件。但是,如果我必须更新配置文件,我只能通过转到 profile/6/ 来访问 PUT。有没有办法让 ModelViewSet 在同一端点公开 PUT,即 profile/?

您可以在任意路径下注册ModelViewSetHTTP方法。

path(
    "profile",
    ProfileRetrieveUpdate.as_view(
        {"put": "partial_update", "get": "retrieve"}
    ),
    name="profile-retrieve-update",
)

您将不得不调整其他内容以及您未提供的内容 pk。 您需要根据需要调整 get_object,而不是覆盖 get_queryset 方法。

from rest_framework import viewsets
from rest_framework.generics import get_object_or_404


class ProfileRetrieveUpdate(viewsets.ModelViewSet):
    serializer_class = UserProfileSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    queryset = UserProfile.objects.all()

    def get_object(self):
        obj = get_object_or_404(self.queryset, user=self.request.user)
        self.check_object_permissions(self.request, obj)
        return obj

    def perform_update(self, serializer):
        serializer.save(user=self.request.user)

现在,如果您 PUT profile/ 它应该会按预期工作。