Django REST framework:在具有def update()的视图集中不允许使用PUT方法

2024-04-29 13:56:38 发布

您现在位置:Python中文网/ 问答频道 /正文

在DRF中,我有一个类似这样的简单视图集:

class MyViewSet(viewsets.ViewSet):       

    def update(self, request):
        # do things...
        return Response(status=status.HTTP_200_OK)

当我尝试一个PUT请求时,我得到一个错误,类似于方法PUT not allowed。如果我使用def put(self, request):所有的事情都可以正常工作。因此,我应该使用def update():而不是def put():,为什么会这样?


Tags: selfputrequestdefstatusupdatedodrf
3条回答

这是因为APIView没有为.put()方法定义处理程序,因此传入的请求无法映射到视图上的处理程序方法,从而引发异常。

(注:viewsets.ViewSet继承自ViewSetMixinAPIView

APIView中的dispatch()方法检查是否为请求method定义了方法处理程序。如果dispatch()方法找到请求方法的处理程序,则返回相应的响应。否则,它会引发异常^{}

根据APIView类中dispatch()方法的源代码:

def dispatch(self, request, *args, **kwargs):       
        ...
        ...    
        try:
            self.initial(request, *args, **kwargs)

            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                 # here handler is fetched for the request method
                 # `http_method_not_allowed` handler is assigned if no handler was found
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed 

            response = handler(request, *args, **kwargs) # handler is called here

        except Exception as exc:
            response = self.handle_exception(exc)

        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response

由于视图中未定义.put()方法处理程序,因此DRF调用回退处理程序.http_method_not_allowed。这会引发MethodNotAllowed异常。

.http_method_not_allowed()的源代码是:

def http_method_not_allowed(self, request, *args, **kwargs):
    """
    If `request.method` does not correspond to a handler method,
    determine what kind of exception to raise.
    """
    raise exceptions.MethodNotAllowed(request.method) # raise an exception 

当您在视图中定义.put()时,它为什么工作?

在视图中定义def put(self, request):时,DRF可以将传入的请求方法映射到视图上的处理程序方法。这导致返回适当的响应,而没有引发异常。

有时POST和PUT是不同的,因为PUT在URL中使用id 在这种情况下,您将得到这个错误:“不允许输入”。

示例:

  • 职位:/api/users/
  • 放置:/api/users/1/

希望能为某人节省很多时间

此代码有类似的“Method PUT not allowed”问题,因为请求中缺少“id”:

class ProfileStep2Serializer(serializers.ModelSerializer):
    class Meta:
        model = Profile
        fields = ('middle_initial', 'mobile_phone', 'address', 'apt_unit_num', 'city', 'state', 'zip')

class Step2ViewSet(viewsets.ModelViewSet):
    serializer_class = ProfileStep2Serializer

    def get_queryset(self):
        return Profile.objects.filter(pk=self.request.user.profile.id)

结果我在序列化程序字段中遗漏了'id',因此PUT请求无法为记录提供id。序列化程序的固定版本如下:

class ProfileStep2Serializer(serializers.ModelSerializer):
    class Meta:
        model = Profile
        fields = ('id', 'middle_initial', 'mobile_phone', 'address', 'apt_unit_num', 'city', 'state', 'zip')

相关问题 更多 >