Django User.set_password导致密码无效

时间:2018-07-22 11:17:08

标签: django django-rest-framework django-users

我正在尝试编写一个序列化程序(在Django REST Framework中)以更新用户的帐户详细信息。这是update()方法:

def update(self, instance, validated_data):
    ...
    if all([item in self.validated_data for item in ["password", "confirm_password", "old_password"]]):
        user = authenticate(username=self.context["request"].user.username, password=self.validated_data["old_password"])
        if user is not None:
            if self.validated_data["password"] == self.validated_data["confirm_password"]:
                validate_password(self.validated_data["password"])
                user.set_password(self.validated_data["password"])
                user.save()
            else:
                raise serializers.ValidationError({"confirm_password": "Passwords do not match"})
        else:
            raise serializers.ValidationError({"old_password": "Password incorrect"})

    self.validated_data.pop("password")

    return super(UserInfoSerializer, self).update(instance, validated_data)

当我使用“密码”,“ confirm_password”和“ old_password”作为字段对视图执行PATCH请求时,它似乎起作用了。然后,当我尝试再次登录该帐户时,它将失败(使用旧密码和新密码)。当我检查管理员设置并查看我要编辑的用户时,得到以下信息:

  

无效的密码格式或未知的哈希算法。

     

原始密码未存储,因此无法查看此用户的密码   密码,但是您可以使用此表单更改密码。

我相信User.set_password()应该可以处理哈希/等。自动,为什么我会出现此错误?

2 个答案:

答案 0 :(得分:2)

您从password中删除了self.validated_data,但没有从传递给超类的validated_data方法的update字典中删除。试试这个:

validated_data.pop("password") # remove self, just leave validated_data

return super(UserInfoSerializer, self).update(instance, validated_data)

答案 1 :(得分:1)

万一有兴趣使用我的代码,这是最终的工作代码:

def update(self, instance, validated_data):
    ...
    if all([item in validated_data for item in ["password", "confirm_password", "old_password"]]):
        user = authenticate(username=instance.username, password=validated_data["old_password"])
        if user is not None and user == instance:
            if validated_data["password"] == validated_data["confirm_password"]:
                validate_password(validated_data["password"])
                instance.set_password(validated_data["password"])
                instance.save()  # change the password on the current instance object, otherwise changes will be overwritten
                login(self.context["request"], instance)  # without this line, the user is auto-logged out upon changing their password
            else:
                raise serializers.ValidationError({"confirm_password": "Passwords do not match"})
        else:
            raise serializers.ValidationError({"old_password": "Password incorrect"})

    if "password" in validated_data:
        validated_data.pop("password")

    return super(UserInfoSerializer, self).update(instance, validated_data)