Django REST Framework更新用户时未修改用户名/邮箱仍提示已存在如何解决
问题根因
报错本质是序列化器运行模式错误导致的。DRF的ModelSerializer初始化时如果只传data参数,会默认运行创建模式,针对模型中设置了unique=True的字段(用户名、邮箱默认都是唯一字段),会直接全表校验是否重复,哪怕你传的是当前用户自身的原有值,也会触发「已存在」的错误。
另外当前代码还有两个隐性bug:
- 密码校验方法没有返回校验后的值,会导致密码字段在校验完成后被置为空
- 视图中手动调用
update方法时传入了原始的request.data而非校验后的validated_data,存在安全风险
修复代码
Serializer.py
class UpdateUserSerializer(serializers.ModelSerializer): class Meta: model = UserAccount fields = ['username', 'email', 'first_name', 'last_name', 'about', 'password'] extra_kwargs = {"password": {"write_only": True}} def validate_password(self, value): user = self.context['request'].user if not user.check_password(value): raise serializers.ValidationError('Incorrect Password') # 必须返回校验后的值 return value def update(self, instance, validated_data): # 密码仅用于身份校验,不需要更新到用户实例,直接弹出 validated_data.pop('password', None) return super().update(instance, validated_data)
Views.py
@api_view(['PATCH']) @permission_classes([IsAuthenticated]) def update_user(request): user = request.user # 初始化时传入instance参数切换为更新模式,partial=True支持部分字段更新 serializer = UpdateUserSerializer(instance=user, data=request.data, context={'request': request}, partial=True) data = {} if serializer.is_valid(): # 直接调用save方法,序列化器会自动执行update逻辑 updated_user = serializer.save() data['user'] = UserSerializer(updated_user).data else: data = serializer.errors return Response(data)
效果说明
修正后序列化器会自动适配更新模式的唯一校验规则:如果提交的用户名/邮箱和当前用户原有值一致,会跳过重复校验;只有修改为其他用户已占用的对应值时,才会抛出重复错误,完全符合预期逻辑。
内容的提问来源于stack exchange,提问作者Luka Reeson
相关产品推荐
相关产品推荐

