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

React axios PATCH请求带Authorization仍报401及Django字段覆盖问题

问题1:最初401错误的原因

最早的PATCH请求你把headers参数写到了请求体(axios.patch第二个参数)的位置,axios没有正确读取到Authorization头,调整参数顺序(把配置项放到第三个参数)后就修复了这个问题。

问题2:数据不更新、传列表报错的原因

  • 你在发送FormData的时候硬指定了Content-Type: application/json,二者完全冲突:FormData对应的Content-Type是multipart/form-data,你手动写死JSON类型会导致Django无法正确解析请求体,拿不到你传的参数。把这个手动设置的Content-Type头删掉就行,axios发送FormData的时候会自动带上正确的Content-Type。
  • 你的序列化器配置错误:你定义的groups字段设置了read_only=True,序列化器不会处理前端传来的groups相关参数,自然不会更新对应字段。而且如果你的UserGroup模型里group是单外键字段,传列表肯定会报类型错误,如果你需要一个用户对应多个用户组,应该把模型字段改成ManyToManyField类型。
  • PATCH请求是更新操作,你的视图里成功后返回201状态码不符合规范,201是创建资源的返回码,更新成功应该返回200。

问题3:更新覆盖原有组的解决方案

方案1:前端拼接+后端适配(最小改动)

  1. 先确认模型字段为多对多类型:
# models.py
class UserGroup(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    groups = models.ManyToManyField(Group, related_name="user_groups")
    # 其他自定义字段
  1. 修改序列化器,让groups支持读写主键列表:
class UserGroupSerializer(serializers.ModelSerializer):
    groups = GroupSerializer(many=True, read_only=True)
    # 新增可写的主键字段,用于接收前端传的组ID列表
    group_ids = serializers.PrimaryKeyRelatedField(
        many=True,
        queryset=Group.objects.all(),
        write_only=True,
        source="groups"
    )

    class Meta:
        model = UserGroup
        fields = '__all__'
  1. 前端修改请求逻辑:不需要用FormData,直接传JSON即可,拿到旧的组ID列表追加新ID后传给group_ids字段:
handleJoin = (e, group) => {
    e.preventDefault();
    const token = `JWT ${localStorage.getItem('token')}`;
    axios.get('http://127.0.0.1:8000/core/current_user/', {
        headers: { Authorization: token }
    })
    .then((user) => {
        return axios.get(`http://127.0.0.1:8000/core/usergroup/${user.data.id}/`, {
            headers: { Authorization: token }
        })
        .then((usergroup) => {
            // 拼接新旧组ID
            const groupIds = usergroup.data.groups.map(g => g.id);
            groupIds.push(group.id);
            return axios.patch(
                `http://127.0.0.1:8000/core/usergroup/${user.data.id}/`,
                { group_ids: groupIds },
                { headers: { Authorization: token } }
            )
        })
    })
    .then((res) => {
        console.log(res.data);
    })
    .catch((err) => {
        console.log(err);
    });
}

方案2:后端直接实现追加逻辑(更安全,避免并发覆盖)

直接在视图的patch方法里处理追加逻辑,不需要前端传全量列表,只需要传要新增的组ID即可,从根源避免覆盖问题:

# views.py
class UserGroupDetail(APIView):
    def patch(self, request, pk):
        usergroup = UserGroup.objects.get(pk=pk)
        # 只取要新增的组ID
        add_group_id = request.data.get("add_group_id")
        if add_group_id:
            # 多对多字段调用add方法追加,不会覆盖原有数据
            usergroup.groups.add(add_group_id)
            return Response(UserGroupSerializer(usergroup).data, status=status.HTTP_200_OK)
        # 保留原有其他字段的更新逻辑
        serializer = UserGroupSerializer(instance=usergroup, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

前端不需要再先请求一次现有组列表,直接传add_group_id参数即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 07:54:08