DRF中密码无法哈希存储问题求助
DRF中Serializer的create方法无法实现密码哈希存储?
我用Django REST Framework开发时,定义了Customer模型和对应的CustomerSerializer,希望把用户密码以哈希形式存储。但尝试了三种重写Serializer的create方法的实现后,密码还是明文存在数据库里(Admin后台能看到)。不过重写save方法做密码哈希时功能正常,想知道是不是Serializer的create方法本来就没法实现这个功能?
模型代码
class CustomerStatus(models.TextChoices): ACTIVE = 'ACT', 'Active' EXPIRED = 'EXP', 'Expired' REVOKED = 'REV', 'Revoked' class Customer(models.Model): email = models.EmailField(max_length=254, unique=True) password = models.CharField(max_length=128) created = models.DateTimeField(auto_now_add=True) status = models.CharField( max_length=3, choices=CustomerStatus.choices, default=CustomerStatus.ACTIVE )
Serializer代码
class CustomerSerializer(serializers.ModelSerializer): class Meta: model = Customer fields = ['email', 'password', 'created', 'status'] extra_kwargs = {'password': {'write_only': True}}
尝试过的三种create方法实现
def create(self, validated_data): validated_data['password'] = make_password(validated_data['password']) return super(CustomerSerializer, self).create(validated_data)
def create(self, validated_data): validated_data['password'] = make_password(validated_data['password']) return super().create(validated_data)
customer = Customer.objects.create( email=validated_data['email'], password=make_password(validated_data['password']), ) return customer
问题解答
首先明确:Serializer的create方法完全可以实现密码哈希存储,你遇到的问题大概率是代码执行逻辑的问题,而非方法本身的限制。
可能的问题排查方向
- 是否正确导入
make_password:必须在Serializer文件顶部导入from django.contrib.auth.hashers import make_password,如果未导入,make_password会抛出异常,导致哈希逻辑未执行(可查看运行日志确认是否有报错)。 - 是否有其他代码覆盖密码值:检查Customer模型是否重写了
save方法,或是否有信号(Signal)在保存实例时重新设置了明文密码;同时确认视图层(如CreateAPIView)没有在调用Serializer后修改密码字段。 - 确认数据库真实存储值:Admin后台的显示可能存在自定义逻辑干扰,建议直接查看数据库表的
password字段,确认是否真的为明文。
你的三种实现的正确性
你的三种create写法本身都是逻辑正确的:
- 写法1和2通过修改
validated_data后调用父类create,父类会使用修改后的参数创建实例,密码应被正确哈希。 - 写法3直接调用
Customer.objects.create并传入哈希后的密码,逻辑上无任何问题。
重写save方法有效的原因
重写模型的save方法时,每次保存都会执行哈希逻辑,相当于在更底层处理密码,避免了上层代码(Serializer、视图)的干扰,但这并不代表Serializer的create方法无法实现该功能。
推荐的正确实现示例
确保导入make_password后,Serializer的create方法可按以下方式编写:
from django.contrib.auth.hashers import make_password from rest_framework import serializers from .models import Customer class CustomerSerializer(serializers.ModelSerializer): class Meta: model = Customer fields = ['email', 'password', 'created', 'status'] extra_kwargs = {'password': {'write_only': True}} def create(self, validated_data): # 对密码进行哈希处理 validated_data['password'] = make_password(validated_data['password']) # 调用父类方法创建实例 return super().create(validated_data)
内容的提问来源于stack exchange,提问作者Omid Shojaee
相关产品推荐
相关产品推荐

