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

Django REST Framework用户信息更新失败,请求排查代码问题

问题排查与修复方案

核心问题分析

你的代码返回500错误主要有以下几个原因:

1. 更新时未传入要修改的用户实例

在patch方法中,初始化RegisterSerializer时只传了data=data,没有指定要更新的instance(即当前登录用户request.user)。这会导致序列化器默认执行创建用户的逻辑,而非更新逻辑,进而触发异常。

2. 序列化器的validate方法存在逻辑缺陷

validate方法中直接检查所有用户的用户名是否存在,当用户更新信息但未修改用户名时,会因为当前用户本身存在而抛出验证错误,导致流程进入异常捕获分支。

3. 未实现update方法处理密码加密

你的序列化器只重写了create方法处理密码加密,但更新密码时没有对应的逻辑,直接保存会导致密码明文存储,同时默认的update逻辑可能无法正确处理自定义字段。


修复后的代码

views.py 修改

class Profile(APIView):
    permission_classes = [IsAuthenticated]
    authentication_classes = [JWTAuthentication]

    def get(self, request):
        user = request.user
        serializer = RegisterSerializer(user)
        return Response(serializer.data)

    def patch(self, request):
        try:
            user = request.user
            # 传入要更新的实例instance,指定partial=True支持部分字段更新
            serializer = RegisterSerializer(user, data=request.data, partial=True)

            if serializer.is_valid():
                serializer.save()
                return Response(
                    {
                        'user': serializer.data,
                        'message': "你的资料已更新"
                    },
                    status=status.HTTP_200_OK
                )
            else:
                return Response(
                    {
                        'user': serializer.errors,
                        'message': "资料更新失败"
                    },
                    status=status.HTTP_400_BAD_REQUEST
                )

        except IntegrityError:
            return Response(
                {
                    'user': None,
                    'message': "该用户名已存在"
                },
                status=status.HTTP_409_CONFLICT
            )
        
        except Exception as e:
            print(e)
            return Response(
                {
                    'user': None,
                    'message': "更新资料时发生错误"
                },
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )

serializer.py 修改

class RegisterSerializer(ModelSerializer):
    class Meta:
        model = User
        fields = ('id', "username", "first_name", "last_name", "email", "password")
        # 密码字段只在创建时必填,更新时可选
        extra_kwargs = {
            'password': {'required': False}
        }

    def validate(self, data):
        # 检查用户名是否存在时,排除当前用户(如果是更新操作)
        if 'username' in data:
            queryset = User.objects.filter(username=data['username'])
            # 如果是更新,过滤掉当前实例
            if self.instance:
                queryset = queryset.exclude(id=self.instance.id)
            if queryset.exists():
                raise serializers.ValidationError("该用户名已存在")
        return data
    
    def create(self, validated_data):
        # 创建用户时处理密码加密
        user = User.objects.create(
            username=validated_data["username"].lower(),
            first_name=validated_data["first_name"],
            last_name=validated_data["last_name"],
            email=validated_data.get("email", "")
        )
        user.set_password(validated_data["password"])
        user.save()
        return user

    def update(self, instance, validated_data):
        # 更新用户时处理密码加密(如果传入了密码)
        password = validated_data.pop('password', None)
        # 更新其他字段
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        # 如果有密码更新,加密后保存
        if password:
            instance.set_password(password)
        instance.save()
        return instance

关键修复点说明

  • 传入instance:更新操作必须指定要修改的用户实例,让序列化器执行更新逻辑而非创建。
  • 优化validate逻辑:更新时排除当前用户,避免未修改用户名时触发重复验证。
  • 实现update方法:处理密码加密逻辑,确保更新密码时也是加密存储,同时正确更新其他字段。
  • 密码字段可选:通过extra_kwargs设置密码在更新时非必填,用户可以选择不修改密码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 04:13:21