You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django REST Framework中Patch请求仅更新CustomUser的detail字段报错

问题:Patch更新CustomUser的detail字段时被要求提供username

场景复现

自定义继承AbstractUser的CustomUser模型:

class CustomUser(AbstractUser):
    detail = models.JSONField(default=dict)
    created_at = models.DateTimeField(auto_now_add=True)    
    updated_at = models.DateTimeField(auto_now=True)  

前端通过Axios发送PATCH请求仅更新detail字段:

var formData = new FormData();
var status = {
    fileObj: this.fileObj.id
}
formData.append("detail", JSON.stringify(status));
axios.patch(
    `/api/customusers/3/`, formData
).then(function (response) {
    console.log("syncdata customuser is saved:", response); 
}).catch(function (response) {
    console.log("syncdata customuser failed:", response);
});

后端ViewSet代码:

class CustomUserViewSet(viewsets.ModelViewSet):
    serializer_class = s.CustomUserSerializer   
    queryset = m.CustomUser.objects.all()

    def update(self, request, *args, **kwargs):
        print("custom user update")
        print(request.data)  # 输出:<QueryDict: {'detail': ['{"fileObj":19}']}>
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data)
        if serializer.is_valid():
            self.perform_update(serializer)
            return Response(serializer.data)
        else:
            print(serializer.errors)  # 输出:{'username': [ErrorDetail(string='This field is required.', code='required')]}

问题原因

  1. 你的CustomUserSerializer继承自ModelSerializer时,会自动将AbstractUser中的username等核心字段标记为必填项。
  2. 默认调用get_serializer未启用部分更新模式,序列化器会校验所有必填字段的存在性,哪怕是PATCH请求仅更新部分字段。

解决方案

方案一:视图中启用partial参数(最简方案)

初始化序列化器时添加partial=True参数,告诉序列化器允许部分字段更新,忽略未传递的必填字段:

def update(self, request, *args, **kwargs):
    print("custom user update")
    print(request.data)
    instance = self.get_object()
    # 添加partial=True启用部分更新
    serializer = self.get_serializer(instance, data=request.data, partial=True)
    if serializer.is_valid():
        self.perform_update(serializer)
        return Response(serializer.data)
    else:
        print(serializer.errors)

方案二:序列化器中动态调整字段必填性

如果需要全局控制更新时的字段规则,可修改序列化器,在更新操作(存在instance)时将username等字段设为非必填:

# 假设你的CustomUserSerializer定义如下
class CustomUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = CustomUser
        # 列出需要暴露的字段,包含AbstractUser字段和自定义字段
        fields = ('id', 'username', 'email', 'detail', 'created_at', 'updated_at')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 当存在instance时(更新操作),调整必填字段
        if self.instance is not None:
            # 将username、email等字段设为非必填
            for field in ['username', 'email']:
                if field in self.fields:
                    self.fields[field].required = False

额外提示

前端用FormData传递JSON格式的detail字段是可行的,后端序列化器会自动将JSON字符串解析为字典(对应模型的JSONField),无需额外处理。

内容的提问来源于stack exchange,提问作者whitebear

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 18:05:21