使用Django Rest Framework遇PATCH方法不允许错误,求解决方案
解决DRF中"Method 'PATCH' not allowed"错误(仅更新指定字段)
Hey Denis, let's work through why you're hitting that "Method 'PATCH' not allowed" error and get your partial update for first_name and password working properly.
1. 问题根源分析
虽然ModelViewSet默认集成了UpdateModelMixin(它自带partial_update方法来支持PATCH请求),但你的自定义partial_update只是返回了201状态码,完全没有处理实际的更新逻辑,甚至没调用父类方法来完成请求的基础校验。另外,你的序列化器字段配置也可能存在问题(比如密码字段的处理),这也会间接导致请求被拦截。
2. 正确实现partial_update并限制更新字段
先修改视图类,让partial_update真正执行更新操作,同时严格限制只允许修改first_name和password:
from rest_framework import viewsets, status from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated from django.contrib.auth.models import User from .serializers import UserSerialize class UpdateUserSet(viewsets.ModelViewSet): permission_classes = (IsAuthenticated,) serializer_class = UserSerialize queryset = User.objects.all() # 注意:ModelViewSet必须配置queryset,否则会导致路由生成异常 def partial_update(self, request, pk=None): user = self.get_object() # 只保留允许更新的字段 allowed_fields = ['first_name', 'password'] update_data = {k: v for k, v in request.data.items() if k in allowed_fields} # 更新first_name if 'first_name' in update_data: user.first_name = update_data['first_name'] # 更新密码(必须用set_password做哈希处理,不能直接赋值) if 'password' in update_data: user.set_password(update_data['password']) user.save() # 返回序列化后的用户数据 serializer = self.get_serializer(user) return Response(serializer.data, status=status.HTTP_200_OK)
3. 修复序列化器的字段配置
你的UserSerialize需要正确处理密码字段(设置为仅写,避免返回明文密码),同时确保first_name支持修改:
from rest_framework import serializers from django.contrib.auth.models import User class UserSerialize(serializers.ModelSerializer): password = serializers.CharField(write_only=True, required=False) first_name = serializers.CharField(required=False) class Meta: model = User fields = ['id', 'username', 'first_name', 'email', 'password'] # 按需包含字段,password仅用于写入
4. 最后检查两个关键点
- 确认路由正确注册了
ModelViewSet,比如用router.register(r'users', UpdateUserSet),DRF会自动生成包含PATCH在内的所有标准路由。 - 确保请求发送到详情路由(比如
/users/{pk}/),PATCH是针对单个资源的操作,不能发送到列表路由。
这样调整后,你的PATCH请求就能正常执行,并且只会更新你指定的first_name和password字段了。
内容的提问来源于stack exchange,提问作者Denis Azi
相关产品推荐
相关产品推荐

