使用Django ModelViewSet时PUT/PATCH方法密码未加密的问题
问题原因与解决方法
原因分析
你的PUT/PATCH请求密码明文存储的核心问题在于update方法的实现:
- 当调用
super().update(instance, validated_data)时,DRF的ModelSerializer会直接将validated_data中的password明文赋值给用户实例的password字段,完全跳过了加密逻辑。 - 同时,
password2是自定义的确认字段,User模型并不存在该字段,如果不提前移除,父类的update方法会抛出字段不存在的异常。
你之前尝试的make_password()或set_password(make_password())无效,大概率是因为没有从validated_data中移除原始的明文password字段,导致父类的update操作覆盖了你手动加密后的密码值。
解决方法
修改update方法,提前处理密码加密逻辑,并移除不需要的password2字段,再调用父类的update方法更新其他字段:
def update(self, instance, validated_data): # 提取并处理密码字段 password = validated_data.pop('password', None) password2 = validated_data.pop('password2', None) # 仅当密码存在且匹配时更新加密密码 if password and password == password2: instance.set_password(password) instance.save() # 处理Profile嵌套字段更新 profile_data = validated_data.pop('profile', {}) profile = instance.profile for key, value in profile_data.items(): setattr(profile, key, value) profile.save() # 更新用户模型的其他字段 return super().update(instance, validated_data)
额外说明
- DRF在执行update操作时会自动调用
validate方法,所以密码匹配的逻辑无需重复编写,只需确保在update时处理加密即可。 set_password()方法会自动使用Django配置的密码哈希算法(默认PBKDF2)处理密码,不需要手动调用make_password(),因为set_password()内部已经封装了这个逻辑。
内容的提问来源于stack exchange,提问作者SLATER
相关产品推荐
相关产品推荐

